Add files via upload
这个提交包含在:
@@ -0,0 +1,653 @@
|
||||
#!/usr/bin/env python3
|
||||
import os
|
||||
import sys
|
||||
import subprocess
|
||||
import platform
|
||||
from pathlib import Path
|
||||
|
||||
# 定义颜色类
|
||||
class Colors:
|
||||
RESET = '\033[0m'
|
||||
RED = '\033[31m'
|
||||
GREEN = '\033[32m'
|
||||
YELLOW = '\033[33m'
|
||||
BLUE = '\033[34m'
|
||||
MAGENTA = '\033[35m'
|
||||
CYAN = '\033[36m'
|
||||
WHITE = '\033[37m'
|
||||
BOLD = '\033[1m'
|
||||
BOLD_GREEN = '\033[1;32m'
|
||||
BOLD_YELLOW = '\033[1;33m'
|
||||
BOLD_CYAN = '\033[1;36m'
|
||||
BOLD_RED = '\033[1;31m'
|
||||
|
||||
# 确保Windows终端支持ANSI颜色
|
||||
def enable_windows_ansi_support():
|
||||
if platform.system() == 'Windows':
|
||||
try:
|
||||
import ctypes
|
||||
kernel32 = ctypes.windll.kernel32
|
||||
kernel32.SetConsoleMode(kernel32.GetStdHandle(-11), 7)
|
||||
except:
|
||||
pass
|
||||
|
||||
# 打印带颜色的文本
|
||||
def print_color(text, color=Colors.RESET):
|
||||
print(f"{color}{text}{Colors.RESET}")
|
||||
|
||||
# 运行命令并返回结果
|
||||
def run_command(cmd, cwd=None, shell=True, check=False):
|
||||
try:
|
||||
result = subprocess.run(cmd, cwd=cwd, shell=shell, check=check,
|
||||
capture_output=True, text=True)
|
||||
return result
|
||||
except subprocess.CalledProcessError as e:
|
||||
return e
|
||||
|
||||
# 构建Windows EXE
|
||||
def build_exe():
|
||||
print_color("\n========================================", Colors.BOLD_CYAN)
|
||||
print_color("Building Windows EXE", Colors.BOLD_YELLOW)
|
||||
print_color("========================================", Colors.BOLD_CYAN)
|
||||
print()
|
||||
|
||||
print_color("Checking PyInstaller...", Colors.CYAN)
|
||||
result = run_command("pip show pyinstaller", check=False)
|
||||
if result.returncode != 0:
|
||||
print_color("PyInstaller not found, installing...", Colors.YELLOW)
|
||||
result = run_command("pip install pyinstaller", check=True)
|
||||
if result.returncode != 0:
|
||||
print_color("Failed to install PyInstaller", Colors.BOLD_RED)
|
||||
input("Press Enter to continue...")
|
||||
return False
|
||||
|
||||
print_color("Building scl.py...", Colors.CYAN)
|
||||
result = run_command(
|
||||
"pyinstaller --onefile --name scl --distpath dist\\exe --workpath build\\exe --specpath build\\exe scl.py",
|
||||
check=True
|
||||
)
|
||||
if result.returncode != 0:
|
||||
print_color("Failed to build scl.py", Colors.BOLD_RED)
|
||||
input("Press Enter to continue...")
|
||||
return False
|
||||
|
||||
print()
|
||||
print_color("EXE build completed!", Colors.BOLD_GREEN)
|
||||
print_color("Output directory: dist\\exe", Colors.GREEN)
|
||||
print()
|
||||
|
||||
print_color("Copying plugins directory...", Colors.CYAN)
|
||||
os.makedirs("dist\\exe\\plugins", exist_ok=True)
|
||||
result = run_command("xcopy /E /I /Y plugins dist\\exe\\plugins", check=False)
|
||||
print()
|
||||
input("Press Enter to continue...")
|
||||
return True
|
||||
|
||||
# 构建Windows EXE - 愚人节版本
|
||||
def build_exe_april_fools():
|
||||
print_color("\n========================================", Colors.BOLD_CYAN)
|
||||
print_color("Building Windows EXE - April Fools Edition", Colors.BOLD_YELLOW)
|
||||
print_color("========================================", Colors.BOLD_CYAN)
|
||||
print()
|
||||
|
||||
print_color("Checking PyInstaller...", Colors.CYAN)
|
||||
result = run_command("pip show pyinstaller", check=False)
|
||||
if result.returncode != 0:
|
||||
print_color("PyInstaller not found, installing...", Colors.YELLOW)
|
||||
result = run_command("pip install pyinstaller", check=True)
|
||||
if result.returncode != 0:
|
||||
print_color("Failed to install PyInstaller", Colors.BOLD_RED)
|
||||
input("Press Enter to continue...")
|
||||
return False
|
||||
|
||||
if not os.path.exists("sdp_yrj.py"):
|
||||
print_color("Error: sdp_yrj.py not found", Colors.BOLD_RED)
|
||||
input("Press Enter to continue...")
|
||||
return False
|
||||
|
||||
print_color("Building sdp_yrj.py...", Colors.CYAN)
|
||||
result = run_command(
|
||||
"pyinstaller --onefile --name sdp_yrj --distpath dist\\exe --workpath build\\exe --specpath build\\exe sdp_yrj.py",
|
||||
check=False
|
||||
)
|
||||
if result.returncode != 0:
|
||||
print_color("Failed to build sdp_yrj.py", Colors.BOLD_RED)
|
||||
else:
|
||||
print_color("Successfully built sdp_yrj.exe", Colors.BOLD_GREEN)
|
||||
|
||||
print()
|
||||
print_color("April Fools EXE build completed!", Colors.BOLD_GREEN)
|
||||
print_color("Output directory: dist\\exe", Colors.GREEN)
|
||||
print()
|
||||
|
||||
print_color("Copying plugins directory...", Colors.CYAN)
|
||||
os.makedirs("dist\\exe\\plugins", exist_ok=True)
|
||||
result = run_command("xcopy /E /I /Y plugins dist\\exe\\plugins", check=False)
|
||||
print()
|
||||
input("Press Enter to continue...")
|
||||
return True
|
||||
|
||||
# 构建Linux DEB - SCL Full Package (via WSL)
|
||||
def build_deb():
|
||||
print_color("\n========================================", Colors.BOLD_CYAN)
|
||||
print_color("Building Linux DEB via WSL", Colors.BOLD_YELLOW)
|
||||
print_color("========================================", Colors.BOLD_CYAN)
|
||||
print()
|
||||
|
||||
print_color("Checking WSL...", Colors.CYAN)
|
||||
result = run_command("wsl echo 'WSL OK'", check=False)
|
||||
if result.returncode != 0:
|
||||
print_color("WSL is not installed or not available", Colors.BOLD_RED)
|
||||
print_color("Please install WSL first:", Colors.YELLOW)
|
||||
print_color(" wsl --install", Colors.GREEN)
|
||||
input("Press Enter to continue...")
|
||||
return False
|
||||
|
||||
print_color("WSL found. Preparing build environment...", Colors.GREEN)
|
||||
|
||||
# 获取当前目录的WSL路径
|
||||
result = run_command("wsl wslpath '%cd%'", check=True)
|
||||
wsl_path = result.stdout.strip()
|
||||
print_color(f"WSL path: {wsl_path}", Colors.BLUE)
|
||||
|
||||
print_color("Creating dist directory...", Colors.CYAN)
|
||||
os.makedirs("dist", exist_ok=True)
|
||||
|
||||
print_color("Copying build script to WSL...", Colors.CYAN)
|
||||
result = run_command(f"wsl cp '{wsl_path}/build_deb_wsl.sh' /tmp/build_deb_wsl.sh", check=True)
|
||||
result = run_command("wsl chmod +x /tmp/build_deb_wsl.sh", check=True)
|
||||
|
||||
print_color("Building DEB package in WSL...", Colors.CYAN)
|
||||
result = run_command(f"wsl /tmp/build_deb_wsl.sh '{wsl_path}'", check=True)
|
||||
if result.returncode != 0:
|
||||
print()
|
||||
print_color("Failed to build DEB package", Colors.BOLD_RED)
|
||||
print_color("Make sure dpkg-deb is available in WSL", Colors.YELLOW)
|
||||
print_color("Run: wsl sudo apt update ^&^& wsl sudo apt install dpkg-dev", Colors.GREEN)
|
||||
input("Press Enter to continue...")
|
||||
return False
|
||||
|
||||
print()
|
||||
print_color("DEB build completed!", Colors.BOLD_GREEN)
|
||||
print_color("Output file: dist\\scl-1.0.0.deb", Colors.GREEN)
|
||||
print()
|
||||
input("Press Enter to continue...")
|
||||
return True
|
||||
|
||||
# 构建Linux DEB - SDP Only (via WSL)
|
||||
def build_sdp_deb():
|
||||
print_color("\n========================================", Colors.BOLD_CYAN)
|
||||
print_color("Building Linux DEB - SDP Only (via WSL)", Colors.BOLD_YELLOW)
|
||||
print_color("========================================", Colors.BOLD_CYAN)
|
||||
print()
|
||||
|
||||
print_color("Checking WSL...", Colors.CYAN)
|
||||
result = run_command("wsl echo 'WSL OK'", check=False)
|
||||
if result.returncode != 0:
|
||||
print_color("WSL is not installed or not available", Colors.BOLD_RED)
|
||||
print_color("Please install WSL first:", Colors.YELLOW)
|
||||
print_color(" wsl --install", Colors.GREEN)
|
||||
input("Press Enter to continue...")
|
||||
return False
|
||||
|
||||
print_color("WSL found. Preparing build environment...", Colors.GREEN)
|
||||
|
||||
# 获取当前目录的WSL路径
|
||||
result = run_command("wsl wslpath '%cd%'", check=True)
|
||||
wsl_path = result.stdout.strip()
|
||||
print_color(f"WSL path: {wsl_path}", Colors.BLUE)
|
||||
|
||||
print_color("Creating dist directory...", Colors.CYAN)
|
||||
os.makedirs("dist", exist_ok=True)
|
||||
|
||||
print_color("Copying build script to WSL...", Colors.CYAN)
|
||||
result = run_command(f"wsl cp '{wsl_path}/build_sdp_deb.sh' /tmp/build_sdp_deb.sh", check=True)
|
||||
|
||||
print_color("Building SDP DEB package in WSL...", Colors.CYAN)
|
||||
result = run_command(f"wsl /tmp/build_sdp_deb.sh '{wsl_path}'", check=True)
|
||||
if result.returncode != 0:
|
||||
print()
|
||||
print_color("Failed to build SDP DEB package", Colors.BOLD_RED)
|
||||
print_color("Make sure dpkg-deb is available in WSL", Colors.YELLOW)
|
||||
print_color("Run: wsl sudo apt update ^&^& wsl sudo apt install dpkg-dev", Colors.GREEN)
|
||||
input("Press Enter to continue...")
|
||||
return False
|
||||
|
||||
print()
|
||||
print_color("SDP DEB build completed!", Colors.BOLD_GREEN)
|
||||
print_color("Output file: dist\\scl-sdp-1.0.0.deb", Colors.GREEN)
|
||||
print()
|
||||
input("Press Enter to continue...")
|
||||
return True
|
||||
|
||||
# 构建Linux DEB - SDP April Fools Edition (via WSL)
|
||||
def build_sdp_deb_april_fools():
|
||||
print_color("\n========================================", Colors.BOLD_CYAN)
|
||||
print_color("Building Linux DEB - SDP April Fools Edition (via WSL)", Colors.BOLD_YELLOW)
|
||||
print_color("========================================", Colors.BOLD_CYAN)
|
||||
print()
|
||||
|
||||
if not os.path.exists("sdp_yrj.py"):
|
||||
print_color("Error: sdp_yrj.py not found", Colors.BOLD_RED)
|
||||
input("Press Enter to continue...")
|
||||
return False
|
||||
|
||||
print_color("Checking WSL...", Colors.CYAN)
|
||||
result = run_command("wsl echo 'WSL OK'", check=False)
|
||||
if result.returncode != 0:
|
||||
print_color("WSL is not installed or not available", Colors.BOLD_RED)
|
||||
print_color("Please install WSL first:", Colors.YELLOW)
|
||||
print_color(" wsl --install", Colors.GREEN)
|
||||
input("Press Enter to continue...")
|
||||
return False
|
||||
|
||||
print_color("WSL found. Preparing build environment...", Colors.GREEN)
|
||||
|
||||
# 获取当前目录的WSL路径
|
||||
result = run_command("wsl wslpath '%cd%'", check=True)
|
||||
wsl_path = result.stdout.strip()
|
||||
print_color(f"WSL path: {wsl_path}", Colors.BLUE)
|
||||
|
||||
print_color("Creating dist directory...", Colors.CYAN)
|
||||
os.makedirs("dist", exist_ok=True)
|
||||
|
||||
# 创建愚人节版本的构建脚本
|
||||
print_color("Creating April Fools build script...", Colors.CYAN)
|
||||
sdp_yrj_deb_script = '''#!/bin/bash
|
||||
set -e
|
||||
|
||||
WSL_PATH="$1"
|
||||
VERSION="1.0.0"
|
||||
|
||||
cd "$WSL_PATH"
|
||||
|
||||
# 创建临时目录
|
||||
mkdir -p deb_temp/usr/local/bin
|
||||
mkdir -p deb_temp/DEBIAN
|
||||
|
||||
# 复制sdp_yrj.py
|
||||
echo "Copying sdp_yrj.py..."
|
||||
cp sdp_yrj.py deb_temp/usr/local/bin/sdp_yrj
|
||||
chmod +x deb_temp/usr/local/bin/sdp_yrj
|
||||
|
||||
# 复制插件目录
|
||||
echo "Copying plugins directory..."
|
||||
mkdir -p deb_temp/usr/local/lib/scl/plugins
|
||||
cp -r plugins/* deb_temp/usr/local/lib/scl/plugins/
|
||||
|
||||
# 创建DEBIAN控制文件
|
||||
echo "Creating DEBIAN control file..."
|
||||
cat > deb_temp/DEBIAN/control << 'EOF'
|
||||
Package: scl-sdp-yrj
|
||||
Version: 1.0.0
|
||||
Section: utils
|
||||
Priority: optional
|
||||
Architecture: all
|
||||
Depends: python3
|
||||
Maintainer: SCL Team
|
||||
Description: SCL Package Manager - April Fools Edition
|
||||
EOF
|
||||
|
||||
# 构建DEB包
|
||||
echo "Building DEB package..."
|
||||
dpkg-deb --build deb_temp "$WSL_PATH/dist/scl-sdp-yrj-1.0.0.deb"
|
||||
|
||||
# 清理
|
||||
echo "Cleaning up..."
|
||||
rm -rf deb_temp
|
||||
|
||||
echo "SDP April Fools DEB build completed!"
|
||||
echo "Output: $WSL_PATH/dist/scl-sdp-yrj-1.0.0.deb"
|
||||
'''
|
||||
|
||||
# 写入构建脚本
|
||||
with open("build_sdp_yrj_deb.sh", "w") as f:
|
||||
f.write(sdp_yrj_deb_script)
|
||||
|
||||
# 为脚本添加执行权限
|
||||
os.chmod("build_sdp_yrj_deb.sh", 0o755)
|
||||
|
||||
print_color("Copying build script to WSL...", Colors.CYAN)
|
||||
result = run_command(f"wsl cp '{wsl_path}/build_sdp_yrj_deb.sh' /tmp/build_sdp_yrj_deb.sh", check=True)
|
||||
result = run_command("wsl chmod +x /tmp/build_sdp_yrj_deb.sh", check=True)
|
||||
|
||||
print_color("Building SDP April Fools DEB package in WSL...", Colors.CYAN)
|
||||
result = run_command(f"wsl /tmp/build_sdp_yrj_deb.sh '{wsl_path}'", check=True)
|
||||
if result.returncode != 0:
|
||||
print()
|
||||
print_color("Failed to build SDP April Fools DEB package", Colors.BOLD_RED)
|
||||
print_color("Make sure dpkg-deb is available in WSL", Colors.YELLOW)
|
||||
print_color("Run: wsl sudo apt update ^&^& wsl sudo apt install dpkg-dev", Colors.GREEN)
|
||||
input("Press Enter to continue...")
|
||||
return False
|
||||
|
||||
print()
|
||||
print_color("SDP April Fools DEB build completed!", Colors.BOLD_GREEN)
|
||||
print_color("Output file: dist\\scl-sdp-yrj-1.0.0.deb", Colors.GREEN)
|
||||
print()
|
||||
input("Press Enter to continue...")
|
||||
return True
|
||||
|
||||
# 构建Linux DEB - Editor Only (via WSL)
|
||||
def build_editor_deb():
|
||||
print_color("\n========================================", Colors.BOLD_CYAN)
|
||||
print_color("Building Linux DEB - Editor Only (via WSL)", Colors.BOLD_YELLOW)
|
||||
print_color("========================================", Colors.BOLD_CYAN)
|
||||
print()
|
||||
|
||||
print_color("Checking WSL...", Colors.CYAN)
|
||||
result = run_command("wsl echo 'WSL OK'", check=False)
|
||||
if result.returncode != 0:
|
||||
print_color("WSL is not installed or not available", Colors.BOLD_RED)
|
||||
print_color("Please install WSL first:", Colors.YELLOW)
|
||||
print_color(" wsl --install", Colors.GREEN)
|
||||
input("Press Enter to continue...")
|
||||
return False
|
||||
|
||||
print_color("WSL found. Preparing build environment...", Colors.GREEN)
|
||||
|
||||
# 获取当前目录的WSL路径
|
||||
result = run_command("wsl wslpath '%cd%'", check=True)
|
||||
wsl_path = result.stdout.strip()
|
||||
print_color(f"WSL path: {wsl_path}", Colors.BLUE)
|
||||
|
||||
print_color("Creating dist directory...", Colors.CYAN)
|
||||
os.makedirs("dist", exist_ok=True)
|
||||
|
||||
print_color("Copying build script to WSL...", Colors.CYAN)
|
||||
result = run_command(f"wsl cp '{wsl_path}/build_editor_deb.sh' /tmp/build_editor_deb.sh", check=True)
|
||||
|
||||
print_color("Building Editor DEB package in WSL...", Colors.CYAN)
|
||||
result = run_command(f"wsl /tmp/build_editor_deb.sh '{wsl_path}'", check=True)
|
||||
if result.returncode != 0:
|
||||
print()
|
||||
print_color("Failed to build Editor DEB package", Colors.BOLD_RED)
|
||||
print_color("Make sure dpkg-deb is available in WSL", Colors.YELLOW)
|
||||
print_color("Run: wsl sudo apt update ^&^& wsl sudo apt install dpkg-dev", Colors.GREEN)
|
||||
input("Press Enter to continue...")
|
||||
return False
|
||||
|
||||
print()
|
||||
print_color("Editor DEB build completed!", Colors.BOLD_GREEN)
|
||||
print_color("Output file: dist\\scl-editor-1.0.0.deb", Colors.GREEN)
|
||||
print()
|
||||
input("Press Enter to continue...")
|
||||
return True
|
||||
|
||||
# 生成macOS Build Script (Mach-O)
|
||||
def generate_macos_script():
|
||||
print_color("\n========================================", Colors.BOLD_CYAN)
|
||||
print_color("Generating macOS Build Script", Colors.BOLD_YELLOW)
|
||||
print_color("========================================", Colors.BOLD_CYAN)
|
||||
print()
|
||||
|
||||
print_color("Creating macOS build script...", Colors.CYAN)
|
||||
script_content = '''#!/bin/bash
|
||||
set -e
|
||||
|
||||
echo "Building SCL for macOS (Mach-O)..."
|
||||
|
||||
VERSION="1.0.0"
|
||||
BUILD_DIR="build/macos"
|
||||
DIST_DIR="dist/macos"
|
||||
|
||||
echo "Checking PyInstaller..."
|
||||
if ! command -v pyinstaller &> /dev/null; then
|
||||
echo "PyInstaller found"
|
||||
else
|
||||
echo "Installing PyInstaller..."
|
||||
pip3 install pyinstaller
|
||||
fi
|
||||
|
||||
echo "Creating build directories..."
|
||||
mkdir -p "$BUILD_DIR"
|
||||
mkdir -p "$DIST_DIR"
|
||||
|
||||
echo "Building scl..."
|
||||
pyinstaller --onefile --name scl --distpath "$DIST_DIR" --workpath "$BUILD_DIR" --specpath "$BUILD_DIR" scl.py
|
||||
|
||||
echo "Building sdp..."
|
||||
pyinstaller --onefile --name sdp --distpath "$DIST_DIR" --workpath "$BUILD_DIR" --specpath "$BUILD_DIR" sdp.py
|
||||
|
||||
echo "Building scl_editor_linux..."
|
||||
pyinstaller --onefile --name scl_editor --distpath "$DIST_DIR" --workpath "$BUILD_DIR" --specpath "$BUILD_DIR" scl_editor_linux.py
|
||||
|
||||
echo "Creating DMG package..."
|
||||
mkdir -p "$DIST_DIR/SCL.app/Contents/MacOS"
|
||||
mkdir -p "$DIST_DIR/SCL.app/Contents/Resources"
|
||||
|
||||
echo "Copying executables..."
|
||||
cp "$DIST_DIR/scl" "$DIST_DIR/SCL.app/Contents/MacOS/"
|
||||
cp "$DIST_DIR/sdp" "$DIST_DIR/SCL.app/Contents/MacOS/"
|
||||
cp "$DIST_DIR/scl_editor" "$DIST_DIR/SCL.app/Contents/MacOS/"
|
||||
|
||||
echo "Creating Info.plist..."
|
||||
cat < "$DIST_DIR/SCL.app/Contents/Info.plist" << EOF
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>scl</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>com.scl.lang</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>SCL</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>$VERSION</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>$VERSION</string>
|
||||
</dict>
|
||||
</plist>
|
||||
EOF
|
||||
|
||||
echo "Building DMG..."
|
||||
if command -v hdiutil &> /dev/null; then
|
||||
hdiutil create -volname "SCL" -srcfolder "$DIST_DIR/SCL.app" -ov -format UDZO "$DIST_DIR/SCL-$VERSION.dmg"
|
||||
echo "DMG created: $DIST_DIR/SCL-$VERSION.dmg"
|
||||
else
|
||||
echo "hdiutil not found, skipping DMG creation"
|
||||
echo "App bundle created: $DIST_DIR/SCL.app"
|
||||
fi
|
||||
|
||||
echo "Build completed!"
|
||||
echo "Output: $DIST_DIR/"
|
||||
'''
|
||||
|
||||
with open("build_macos.sh", "w") as f:
|
||||
f.write(script_content)
|
||||
|
||||
# 为脚本添加执行权限
|
||||
os.chmod("build_macos.sh", 0o755)
|
||||
|
||||
print()
|
||||
print_color("macOS build script created: build_macos.sh", Colors.BOLD_GREEN)
|
||||
print()
|
||||
print_color("Instructions:", Colors.BOLD_YELLOW)
|
||||
print_color("1. Copy build_macos.sh to a macOS system", Colors.GREEN)
|
||||
print_color("2. Make it executable: chmod +x build_macos.sh", Colors.GREEN)
|
||||
print_color("3. Run it: ./build_macos.sh", Colors.GREEN)
|
||||
print()
|
||||
input("Press Enter to continue...")
|
||||
return True
|
||||
|
||||
# 生成SDP macOS Build Script
|
||||
def generate_sdp_macos_script():
|
||||
print_color("\n========================================", Colors.BOLD_CYAN)
|
||||
print_color("Generating SDP macOS Build Script", Colors.BOLD_YELLOW)
|
||||
print_color("========================================", Colors.BOLD_CYAN)
|
||||
print()
|
||||
|
||||
print_color("Creating SDP macOS build script...", Colors.CYAN)
|
||||
script_content = '''#!/bin/bash
|
||||
set -e
|
||||
|
||||
echo "Building SDP for macOS (Mach-O)..."
|
||||
|
||||
VERSION="1.0.0"
|
||||
BUILD_DIR="build/sdp-macos"
|
||||
DIST_DIR="dist/sdp-macos"
|
||||
|
||||
echo "Checking PyInstaller..."
|
||||
if ! command -v pyinstaller &> /dev/null; then
|
||||
echo "Installing PyInstaller..."
|
||||
pip3 install pyinstaller
|
||||
else
|
||||
echo "PyInstaller found"
|
||||
fi
|
||||
|
||||
echo "Creating build directories..."
|
||||
mkdir -p "$BUILD_DIR"
|
||||
mkdir -p "$DIST_DIR"
|
||||
|
||||
echo "Building SDP..."
|
||||
pyinstaller --onefile --name sdp --distpath "$DIST_DIR" --workpath "$BUILD_DIR" --specpath "$BUILD_DIR" sdp.py
|
||||
|
||||
echo "Creating SDP App Bundle..."
|
||||
APP_DIR="$DIST_DIR/SDP.app"
|
||||
mkdir -p "$APP_DIR/Contents/MacOS"
|
||||
mkdir -p "$APP_DIR/Contents/Resources"
|
||||
|
||||
echo "Copying executable..."
|
||||
cp "$DIST_DIR/sdp" "$APP_DIR/Contents/MacOS/"
|
||||
|
||||
echo "Creating Info.plist..."
|
||||
cat > "$APP_DIR/Contents/Info.plist" << 'EOF'
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>sdp</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>com.scl.sdp</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>SDP</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>$VERSION</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>$VERSION</string>
|
||||
</dict>
|
||||
</plist>
|
||||
EOF
|
||||
|
||||
echo "Building SDP DMG..."
|
||||
if command -v hdiutil &> /dev/null; then
|
||||
hdiutil create -volname "SDP" -srcfolder "$APP_DIR" -ov -format UDZO "$DIST_DIR/SDP-$VERSION.dmg"
|
||||
echo "DMG created: $DIST_DIR/SDP-$VERSION.dmg"
|
||||
else
|
||||
echo "hdiutil not found, skipping DMG creation"
|
||||
echo "App bundle created: $APP_DIR"
|
||||
fi
|
||||
|
||||
echo "SDP build completed!"
|
||||
echo "Output: $DIST_DIR/"
|
||||
'''
|
||||
|
||||
with open("build_sdp_macos.sh", "w") as f:
|
||||
f.write(script_content)
|
||||
|
||||
# 为脚本添加执行权限
|
||||
os.chmod("build_sdp_macos.sh", 0o755)
|
||||
|
||||
print()
|
||||
print_color("SDP macOS build script created: build_sdp_macos.sh", Colors.BOLD_GREEN)
|
||||
print()
|
||||
print_color("Instructions:", Colors.BOLD_YELLOW)
|
||||
print_color("1. Copy build_sdp_macos.sh to a macOS system", Colors.GREEN)
|
||||
print_color("2. Make it executable: chmod +x build_sdp_macos.sh", Colors.GREEN)
|
||||
print_color("3. Run it: ./build_sdp_macos.sh", Colors.GREEN)
|
||||
print()
|
||||
input("Press Enter to continue...")
|
||||
return True
|
||||
|
||||
# 构建所有 (EXE + DEB)
|
||||
def build_all():
|
||||
print_color("\n========================================", Colors.BOLD_CYAN)
|
||||
print_color("Building All Packages (EXE + DEB)", Colors.BOLD_YELLOW)
|
||||
print_color("========================================", Colors.BOLD_CYAN)
|
||||
print()
|
||||
|
||||
print_color("Starting Windows EXE build...", Colors.CYAN)
|
||||
print()
|
||||
if not build_exe():
|
||||
return False
|
||||
|
||||
print_color("Starting Linux DEB build...", Colors.CYAN)
|
||||
print()
|
||||
if not build_deb():
|
||||
return False
|
||||
|
||||
print()
|
||||
print_color("All builds completed!", Colors.BOLD_GREEN)
|
||||
print()
|
||||
input("Press Enter to continue...")
|
||||
return True
|
||||
|
||||
# 显示菜单
|
||||
def show_menu():
|
||||
while True:
|
||||
print_color("========================================", Colors.BOLD_CYAN)
|
||||
print_color("SCL Build Tool", Colors.BOLD_YELLOW)
|
||||
print_color("========================================", Colors.BOLD_CYAN)
|
||||
print()
|
||||
|
||||
print_color("Please select build type:", Colors.BOLD_YELLOW)
|
||||
print_color("[1] Build Windows EXE", Colors.GREEN)
|
||||
print_color("[2] Build Linux DEB - SCL Full Package (via WSL)", Colors.GREEN)
|
||||
print_color("[3] Build Linux DEB - SDP Only (via WSL)", Colors.GREEN)
|
||||
print_color("[4] Build Linux DEB - Editor Only (via WSL)", Colors.GREEN)
|
||||
print_color("[5] Generate macOS Build Script (Mach-O)", Colors.GREEN)
|
||||
print_color("[6] Generate SDP macOS Build Script", Colors.GREEN)
|
||||
print_color("[7] Build All (EXE + DEB)", Colors.GREEN)
|
||||
print_color("[8] Build Windows EXE - April Fools Edition", Colors.GREEN)
|
||||
print_color("[9] Build Linux DEB - SDP April Fools Edition (via WSL)", Colors.GREEN)
|
||||
print_color("[10] Exit", Colors.GREEN)
|
||||
print()
|
||||
|
||||
try:
|
||||
choice = input(f"{Colors.BOLD_CYAN}Enter option (1-10):{Colors.RESET} ")
|
||||
print()
|
||||
|
||||
if choice == "1":
|
||||
build_exe()
|
||||
elif choice == "2":
|
||||
build_deb()
|
||||
elif choice == "3":
|
||||
build_sdp_deb()
|
||||
elif choice == "4":
|
||||
build_editor_deb()
|
||||
elif choice == "5":
|
||||
generate_macos_script()
|
||||
elif choice == "6":
|
||||
generate_sdp_macos_script()
|
||||
elif choice == "7":
|
||||
build_all()
|
||||
elif choice == "8":
|
||||
build_exe_april_fools()
|
||||
elif choice == "9":
|
||||
build_sdp_deb_april_fools()
|
||||
elif choice == "10":
|
||||
break
|
||||
else:
|
||||
print_color("Invalid option, please try again", Colors.BOLD_RED)
|
||||
print()
|
||||
except KeyboardInterrupt:
|
||||
print()
|
||||
break
|
||||
except Exception as e:
|
||||
print_color(f"An error occurred: {e}", Colors.BOLD_RED)
|
||||
print()
|
||||
|
||||
print_color("\nThank you for using SCL Build Tool!", Colors.BOLD_YELLOW)
|
||||
print()
|
||||
input("Press Enter to exit...")
|
||||
|
||||
# 主函数
|
||||
if __name__ == "__main__":
|
||||
enable_windows_ansi_support()
|
||||
show_menu()
|
||||
@@ -0,0 +1,424 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
SCL to Python Compiler
|
||||
Converts SCL code to Python code with interpreter and plugins embedded
|
||||
"""
|
||||
|
||||
import sys
|
||||
import os
|
||||
import re
|
||||
import ast
|
||||
|
||||
|
||||
class PluginAnalyzer:
|
||||
"""Analyze plugin code to understand its syntax and implementation"""
|
||||
|
||||
def __init__(self):
|
||||
self.plugins = {} # Cache for analyzed plugins
|
||||
self.plugin_file_cache = {} # Cache for plugin file contents
|
||||
|
||||
def analyze_plugin(self, plugin_name):
|
||||
"""Analyze a plugin's code"""
|
||||
if plugin_name in self.plugins:
|
||||
return self.plugins[plugin_name]
|
||||
|
||||
# Get the plugins directory path relative to the script
|
||||
script_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
plugin_file = os.path.join(script_dir, 'plugins', f'{plugin_name}.py')
|
||||
|
||||
if not os.path.exists(plugin_file):
|
||||
print(f"Error: Plugin file '{plugin_file}' not found")
|
||||
return None
|
||||
|
||||
# Check if file content is cached
|
||||
mtime = os.path.getmtime(plugin_file)
|
||||
cache_key = (plugin_file, mtime)
|
||||
if cache_key in self.plugin_file_cache:
|
||||
code = self.plugin_file_cache[cache_key]
|
||||
else:
|
||||
try:
|
||||
with open(plugin_file, 'r', encoding='utf-8') as f:
|
||||
code = f.read()
|
||||
# Cache the file content
|
||||
self.plugin_file_cache[cache_key] = code
|
||||
except Exception as e:
|
||||
print(f"Error reading plugin file {plugin_file}: {e}")
|
||||
return None
|
||||
|
||||
# Parse the code
|
||||
try:
|
||||
tree = ast.parse(code)
|
||||
except SyntaxError as e:
|
||||
print(f"Error parsing plugin {plugin_name}: Syntax error at line {e.lineno}, column {e.offset}: {e.msg}")
|
||||
return None
|
||||
|
||||
# Extract information
|
||||
try:
|
||||
plugin_info = self._extract_plugin_info(tree, plugin_name)
|
||||
plugin_info['code'] = code
|
||||
self.plugins[plugin_name] = plugin_info
|
||||
return plugin_info
|
||||
except Exception as e:
|
||||
print(f"Error extracting plugin information from {plugin_name}: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
return None
|
||||
|
||||
def _extract_plugin_info(self, tree, plugin_name):
|
||||
"""Extract plugin information from AST"""
|
||||
info = {
|
||||
'name': plugin_name,
|
||||
'imports': [],
|
||||
'dependencies': [],
|
||||
'commands': {},
|
||||
'class_name': f'{plugin_name.capitalize()}Plugin'
|
||||
}
|
||||
|
||||
# Get the plugins directory path relative to the script
|
||||
script_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
plugins_dir = os.path.join(script_dir, 'plugins')
|
||||
|
||||
# Extract imports and dependencies
|
||||
for node in ast.walk(tree):
|
||||
if isinstance(node, ast.Import):
|
||||
for alias in node.names:
|
||||
info['imports'].append(alias.name)
|
||||
# Check if this is a plugin dependency
|
||||
if os.path.exists(plugins_dir) and alias.name in os.listdir(plugins_dir) and os.path.isfile(os.path.join(plugins_dir, f'{alias.name}.py')):
|
||||
info['dependencies'].append(alias.name)
|
||||
elif isinstance(node, ast.ImportFrom):
|
||||
if node.module:
|
||||
info['imports'].append(node.module)
|
||||
# Check if this is a plugin dependency
|
||||
if os.path.exists(plugins_dir) and node.module in os.listdir(plugins_dir) and os.path.isfile(os.path.join(plugins_dir, f'{node.module}.py')):
|
||||
info['dependencies'].append(node.module)
|
||||
|
||||
# Extract command patterns from parse_statement
|
||||
elif isinstance(node, ast.FunctionDef) and node.name == 'parse_statement':
|
||||
self._extract_commands_from_parse(node, info)
|
||||
|
||||
return info
|
||||
|
||||
def _extract_commands_from_parse(self, node, info):
|
||||
"""Extract command patterns from parse_statement function"""
|
||||
for child in ast.walk(node):
|
||||
if isinstance(child, ast.Compare) and isinstance(child.left, ast.Subscript):
|
||||
# Check for tokens[pos][1] == 'command'
|
||||
if self._is_tokens_access(child.left):
|
||||
if isinstance(child.comparators[0], ast.Constant):
|
||||
command = child.comparators[0].value
|
||||
if isinstance(command, str):
|
||||
info['commands'][command] = {'type': 'direct'}
|
||||
|
||||
elif isinstance(child, ast.Compare) and isinstance(child.left, ast.Name):
|
||||
# Check for command_suffix == 'c'
|
||||
if child.left.id == 'command_suffix':
|
||||
if isinstance(child.comparators[0], ast.Constant):
|
||||
suffix = child.comparators[0].value
|
||||
if isinstance(suffix, str):
|
||||
info['commands'][f'sui-{suffix}'] = {'type': 'sui'}
|
||||
|
||||
def _is_tokens_access(self, node):
|
||||
"""Check if node is tokens[pos][1]"""
|
||||
if (isinstance(node, ast.Subscript) and
|
||||
isinstance(node.value, ast.Name) and
|
||||
node.value.id == 'tokens'):
|
||||
if isinstance(node.slice, ast.Constant) or isinstance(node.slice, ast.Name):
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
class SCLCompiler:
|
||||
def __init__(self):
|
||||
self.variables = {}
|
||||
self.imports = set()
|
||||
self.indent_level = 0
|
||||
self.plugin_analyzer = PluginAnalyzer()
|
||||
self.loaded_plugins = set()
|
||||
|
||||
def _detect_plugin_conflicts(self, resolved_plugins):
|
||||
"""Detect command conflicts between plugins"""
|
||||
command_map = {}
|
||||
conflicts = []
|
||||
|
||||
for plugin_name in resolved_plugins:
|
||||
plugin_info = self.plugin_analyzer.analyze_plugin(plugin_name)
|
||||
if not plugin_info:
|
||||
continue
|
||||
|
||||
for command in plugin_info.get('commands', {}):
|
||||
if command in command_map:
|
||||
conflicts.append((command, command_map[command], plugin_name))
|
||||
else:
|
||||
command_map[command] = plugin_name
|
||||
|
||||
return conflicts
|
||||
|
||||
def compile(self, scl_code, filename="input.scl", minify=False):
|
||||
"""Compile SCL code to Python code with embedded interpreter and plugins"""
|
||||
lines = scl_code.split('\n')
|
||||
|
||||
# First pass: collect plugins
|
||||
plugins_to_load = []
|
||||
for line in lines:
|
||||
if line.startswith('simp{') and line.endswith('}'):
|
||||
import_content = line[5:-1].strip()
|
||||
if not import_content.startswith('scl :'):
|
||||
plugins_to_load.append(import_content)
|
||||
|
||||
# Resolve plugin dependencies
|
||||
resolved_plugins = self._resolve_plugin_dependencies(plugins_to_load)
|
||||
|
||||
# Detect plugin conflicts
|
||||
conflicts = self._detect_plugin_conflicts(resolved_plugins)
|
||||
if conflicts:
|
||||
print("Warning: Command conflicts detected between plugins:")
|
||||
for command, plugin1, plugin2 in conflicts:
|
||||
print(f" Command '{command}' is defined in both {plugin1} and {plugin2}")
|
||||
print(" The last loaded plugin will take precedence.")
|
||||
|
||||
# Load SCL interpreter code
|
||||
scl_interpreter_code = self._load_scl_interpreter()
|
||||
|
||||
# Load plugin codes
|
||||
plugin_codes = {}
|
||||
for plugin_name in resolved_plugins:
|
||||
plugin_info = self.plugin_analyzer.analyze_plugin(plugin_name)
|
||||
if plugin_info:
|
||||
plugin_codes[plugin_name] = plugin_info['code']
|
||||
|
||||
# Generate embedded Python code
|
||||
python_code = self._generate_embedded_code(scl_code, scl_interpreter_code, plugin_codes, filename, minify)
|
||||
return python_code
|
||||
|
||||
def _resolve_plugin_dependencies(self, plugins_to_load):
|
||||
"""Resolve plugin dependencies and return an ordered list"""
|
||||
resolved = set()
|
||||
unresolved = set(plugins_to_load)
|
||||
order = []
|
||||
|
||||
print(f"Resolving dependencies for plugins: {plugins_to_load}")
|
||||
|
||||
while unresolved:
|
||||
# Find plugins with all dependencies resolved
|
||||
progress = False
|
||||
for plugin_name in list(unresolved):
|
||||
plugin_info = self.plugin_analyzer.analyze_plugin(plugin_name)
|
||||
if not plugin_info:
|
||||
print(f"Warning: Skipping plugin {plugin_name} due to analysis errors")
|
||||
unresolved.remove(plugin_name)
|
||||
continue
|
||||
|
||||
# Check if all dependencies are resolved
|
||||
dependencies = plugin_info.get('dependencies', [])
|
||||
print(f"Plugin {plugin_name} has dependencies: {dependencies}")
|
||||
|
||||
if all(dep in resolved for dep in dependencies):
|
||||
# Add to resolved and order
|
||||
resolved.add(plugin_name)
|
||||
order.append(plugin_name)
|
||||
unresolved.remove(plugin_name)
|
||||
progress = True
|
||||
print(f"Resolved plugin: {plugin_name}")
|
||||
|
||||
# Add dependencies to unresolved if not already processed
|
||||
for dep in dependencies:
|
||||
if dep not in resolved and dep not in unresolved:
|
||||
print(f"Adding dependency {dep} for plugin {plugin_name}")
|
||||
unresolved.add(dep)
|
||||
|
||||
if not progress:
|
||||
# No progress made, break to avoid infinite loop
|
||||
print(f"Warning: Unable to resolve all dependencies. Remaining: {unresolved}")
|
||||
break
|
||||
|
||||
print(f"Resolved plugin order: {order}")
|
||||
return order
|
||||
|
||||
def _minify_code(self, code):
|
||||
"""Minify Python code by removing comments and whitespace"""
|
||||
lines = code.split('\n')
|
||||
minified_lines = []
|
||||
in_multiline_comment = False
|
||||
|
||||
for line in lines:
|
||||
# Skip empty lines
|
||||
if not line.strip():
|
||||
continue
|
||||
|
||||
# Handle multiline comments
|
||||
if '"""' in line or "''" in line:
|
||||
in_multiline_comment = not in_multiline_comment
|
||||
continue
|
||||
|
||||
if in_multiline_comment:
|
||||
continue
|
||||
|
||||
# Remove single-line comments
|
||||
if '#' in line:
|
||||
line = line.split('#')[0].rstrip()
|
||||
if not line:
|
||||
continue
|
||||
|
||||
# Remove leading and trailing whitespace
|
||||
line = line.strip()
|
||||
if line:
|
||||
minified_lines.append(line)
|
||||
|
||||
return '\n'.join(minified_lines)
|
||||
|
||||
def _load_scl_interpreter(self):
|
||||
"""Load SCL interpreter code"""
|
||||
try:
|
||||
# Get the script directory
|
||||
script_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
scl_path = os.path.join(script_dir, 'scl.py')
|
||||
|
||||
with open(scl_path, 'r', encoding='utf-8') as f:
|
||||
code = f.read()
|
||||
|
||||
# Remove the main function execution at the end
|
||||
lines = code.split('\n')
|
||||
filtered_lines = []
|
||||
in_main_block = False
|
||||
|
||||
for line in lines:
|
||||
if line.strip() == 'if __name__ == "__main__":':
|
||||
in_main_block = True
|
||||
continue
|
||||
if in_main_block:
|
||||
if line.strip() and not line.startswith(' '):
|
||||
in_main_block = False
|
||||
else:
|
||||
continue
|
||||
filtered_lines.append(line)
|
||||
|
||||
return '\n'.join(filtered_lines)
|
||||
except Exception as e:
|
||||
print(f"Error loading SCL interpreter: {e}")
|
||||
return ""
|
||||
|
||||
def _generate_header(self, filename):
|
||||
"""Generate the header for the embedded code"""
|
||||
return [
|
||||
'#!/usr/bin/env python3',
|
||||
f'# Generated from {filename} by SCL Compiler',
|
||||
'# Embedded SCL interpreter and plugins',
|
||||
''
|
||||
]
|
||||
|
||||
def _generate_interpreter_code(self, scl_interpreter_code, minify):
|
||||
"""Generate the SCL interpreter code"""
|
||||
code = ['\n# ==== SCL INTERPRETER ====\n']
|
||||
if minify:
|
||||
code.append(self._minify_code(scl_interpreter_code))
|
||||
else:
|
||||
code.append(scl_interpreter_code)
|
||||
code.append('')
|
||||
return code
|
||||
|
||||
def _generate_plugin_codes(self, plugin_codes, minify):
|
||||
"""Generate the plugin codes"""
|
||||
code = []
|
||||
for plugin_name, plugin_code in plugin_codes.items():
|
||||
code.append(f'\n# ==== PLUGIN: {plugin_name} ====\n')
|
||||
if minify:
|
||||
code.append(self._minify_code(plugin_code))
|
||||
else:
|
||||
code.append(plugin_code)
|
||||
code.append('')
|
||||
return code
|
||||
|
||||
def _generate_main_function(self, plugin_codes, scl_code):
|
||||
"""Generate the main function code"""
|
||||
code = ['\n# ==== MAIN EXECUTION ====\n\ndef main():\n """Run the embedded SCL code"""\n print("Running embedded SCL code...")\n print("=" * 50)\n \n # Create SCL interpreter\n interpreter = SCLInterpreter()\n \n # Load plugins\n']
|
||||
|
||||
# Add plugin loading code
|
||||
for plugin_name in plugin_codes:
|
||||
code.append(f" interpreter.load_plugin('{plugin_name}')\n")
|
||||
|
||||
# Add SCL code execution
|
||||
code.append('\n # SCL code to execute\n scl_code = """')
|
||||
# 安全地嵌入 SCL 代码,处理三引号
|
||||
for line in scl_code.split('\n'):
|
||||
code.append(line.replace('"""', '\\"""'))
|
||||
code.append('\n')
|
||||
code.append('"""\n')
|
||||
|
||||
# Add execution code
|
||||
code.append('\n # Execute SCL code\n try:\n success = interpreter.execute(scl_code, "embedded")\n if not success:\n print("Error: Failed to execute SCL code")\n except Exception as e:\n print(f"Error: {e}")\n \n print("=" * 50)\n print("Execution completed.")\n\n\nif __name__ == "__main__":\n main()\n')
|
||||
|
||||
return code
|
||||
|
||||
def _generate_embedded_code(self, scl_code, scl_interpreter_code, plugin_codes, filename, minify=False):
|
||||
"""Generate embedded Python code"""
|
||||
# Use a single string buffer for more efficient concatenation
|
||||
code_buffer = []
|
||||
|
||||
# Add header
|
||||
code_buffer.extend(self._generate_header(filename))
|
||||
|
||||
# Add SCL interpreter code
|
||||
code_buffer.extend(self._generate_interpreter_code(scl_interpreter_code, minify))
|
||||
|
||||
# Add plugin codes
|
||||
code_buffer.extend(self._generate_plugin_codes(plugin_codes, minify))
|
||||
|
||||
# Add main function
|
||||
code_buffer.extend(self._generate_main_function(plugin_codes, scl_code))
|
||||
|
||||
return ''.join(code_buffer)
|
||||
|
||||
|
||||
def main():
|
||||
"""Main function"""
|
||||
import argparse
|
||||
|
||||
# Parse command line arguments
|
||||
parser = argparse.ArgumentParser(description='SCL to Python Compiler')
|
||||
parser.add_argument('input_file', help='Input SCL file')
|
||||
parser.add_argument('output_file', nargs='?', help='Output Python file (optional, default: stdout)')
|
||||
parser.add_argument('-m', '--minify', action='store_true', help='Minify the generated code')
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
input_file = args.input_file
|
||||
output_file = args.output_file
|
||||
minify = args.minify
|
||||
|
||||
# Check if input file exists
|
||||
if not os.path.exists(input_file):
|
||||
print(f"Error: Input file '{input_file}' not found")
|
||||
sys.exit(1)
|
||||
|
||||
# Read SCL code
|
||||
try:
|
||||
with open(input_file, 'r', encoding='utf-8') as f:
|
||||
scl_code = f.read()
|
||||
except Exception as e:
|
||||
print(f"Error reading file: {e}")
|
||||
sys.exit(1)
|
||||
|
||||
# Compile to Python
|
||||
compiler = SCLCompiler()
|
||||
python_code = compiler.compile(scl_code, input_file, minify)
|
||||
|
||||
# Output
|
||||
if output_file:
|
||||
try:
|
||||
with open(output_file, 'w', encoding='utf-8') as f:
|
||||
f.write(python_code)
|
||||
print(f"Successfully compiled {input_file} to {output_file}")
|
||||
if minify:
|
||||
print("The file has been minified to reduce size.")
|
||||
else:
|
||||
print("The file includes embedded SCL interpreter and plugins.")
|
||||
except Exception as e:
|
||||
print(f"Error writing file: {e}")
|
||||
sys.exit(1)
|
||||
else:
|
||||
print(python_code)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
在新工单中引用
屏蔽一个用户