diff --git a/.gitea/workflows/release.yml b/.gitea/workflows/release.yml index c696ba8..13c42a0 100644 --- a/.gitea/workflows/release.yml +++ b/.gitea/workflows/release.yml @@ -25,23 +25,36 @@ jobs: - name: Install System and Cross-Compilation Build Dependencies run: | + echo "=== SYSTEM DIAGNOSTICS ===" + uname -a || true + python3 --version || true + SUDO="" + if [ "$(id -u)" -ne 0 ] && command -v sudo >/dev/null 2>&1; then + SUDO="sudo" + fi if command -v apt-get >/dev/null 2>&1; then - echo "[*] Installing Python shared libraries, headers, NSIS, and build dependencies..." - SUDO="" - if [ "$(id -u)" -ne 0 ] && command -v sudo >/dev/null 2>&1; then - SUDO="sudo" - fi + echo "[*] Installing Python shared libraries, headers, NSIS via apt-get..." export DEBIAN_FRONTEND=noninteractive - $SUDO apt-get update -y || true + $SUDO apt-get clean || true + $SUDO apt-get update --allow-releaseinfo-change -y || $SUDO apt-get update -y || true PY_VER=$(python3 -c "import sys; print(f'{sys.version_info.major}.{sys.version_info.minor}')" 2>/dev/null || echo "3.9") echo "[*] Detected Python version: ${PY_VER}" - for pkg in nsis "libpython${PY_VER}" "libpython${PY_VER}-dev" "python${PY_VER}-dev" python3-dev libpython3-dev build-essential gcc make curl tar gzip zip unzip; do - $SUDO apt-get install -y --no-install-recommends "$pkg" || true + $SUDO apt-get install -y --allow-unauthenticated --no-install-recommends \ + nsis "libpython${PY_VER}" "libpython${PY_VER}-dev" "python${PY_VER}-dev" \ + python3-dev libpython3-dev build-essential gcc make curl tar gzip zip unzip || true + for pkg in nsis "libpython${PY_VER}" "libpython${PY_VER}-dev" "python${PY_VER}-dev" python3-dev libpython3-dev build-essential; do + $SUDO apt-get install -y --allow-unauthenticated --no-install-recommends "$pkg" || true done echo "[*] Verifying makensis:" which makensis || echo "makensis not in PATH" echo "[*] Verifying libpython shared library:" find /usr/lib /usr/local/lib -name "libpython*.so*" 2>/dev/null || true + elif command -v apk >/dev/null 2>&1; then + echo "[*] Installing dependencies via apk..." + $SUDO apk add --no-cache nsis python3-dev build-base gcc make curl tar gzip zip unzip || true + elif command -v dnf >/dev/null 2>&1; then + echo "[*] Installing dependencies via dnf..." + $SUDO dnf install -y mingw32-nsis nsis python3-devel gcc make curl tar gzip zip unzip || true fi python3 compilation/ensure_pip.py python3 -m pip install --upgrade pip --break-system-packages 2>/dev/null || python3 -m pip install --upgrade pip 2>/dev/null || true diff --git a/compilation/package_dist.py b/compilation/package_dist.py index 1764d68..9b41446 100644 --- a/compilation/package_dist.py +++ b/compilation/package_dist.py @@ -136,24 +136,63 @@ def create_windows_exe_zipapp(script_name, exe_name): print(f"[+] Successfully cross-compiled Windows PE executable: {exe_name}.exe (PE Stub attached: {bool(stub_bytes)})") +def ensure_makensis(): + """Finds or attempts to install makensis on the current system.""" + for cmd in ["makensis", "/usr/bin/makensis", "/usr/local/bin/makensis", + r"C:\Program Files (x86)\NSIS\makensis.exe", + r"C:\Program Files\NSIS\makensis.exe"]: + p = shutil.which(cmd) if not os.path.isabs(cmd) else cmd + if p and (os.path.exists(p) or shutil.which(p)): + return p + + if platform.system() == "Linux": + print("[*] Attempting to install 'nsis' package dynamically...") + sudo = ["sudo"] if hasattr(os, "geteuid") and os.geteuid() != 0 and shutil.which("sudo") else [] + if shutil.which("apt-get"): + try: + subprocess.run(sudo + ["apt-get", "update", "--allow-releaseinfo-change", "-y"], check=False) + subprocess.run(sudo + ["apt-get", "install", "-y", "--no-install-recommends", "nsis"], check=False) + except Exception as e: + print(f"[!] Warning: Dynamic apt install failed: {e}") + elif shutil.which("apk"): + try: + subprocess.run(sudo + ["apk", "add", "--no-cache", "nsis"], check=False) + except Exception: + pass + elif shutil.which("dnf"): + try: + subprocess.run(sudo + ["dnf", "install", "-y", "mingw32-nsis", "nsis"], check=False) + except Exception: + pass + + for cmd in ["makensis", "/usr/bin/makensis", "/usr/local/bin/makensis"]: + p = shutil.which(cmd) if not os.path.isabs(cmd) else cmd + if p and (os.path.exists(p) or shutil.which(p)): + return p + + return None + + +def ensure_libpython(): + """Attempts to install libpython shared library on Debian/Ubuntu for PyInstaller.""" + if platform.system() == "Linux" and shutil.which("apt-get"): + py_ver = f"{sys.version_info.major}.{sys.version_info.minor}" + sudo = ["sudo"] if hasattr(os, "geteuid") and os.geteuid() != 0 and shutil.which("sudo") else [] + try: + subprocess.run(sudo + ["apt-get", "update", "--allow-releaseinfo-change", "-y"], check=False) + subprocess.run(sudo + ["apt-get", "install", "-y", "--no-install-recommends", f"libpython{py_ver}", "python3-dev", f"python{py_ver}-dev"], check=False) + except Exception: + pass + + def compile_nsis_installers(): """Compiles NSIS installers if makensis is available (native Linux/Windows).""" - makensis_cmd = None - if shutil.which("makensis"): - makensis_cmd = [shutil.which("makensis")] - elif os.path.exists("/usr/bin/makensis"): - makensis_cmd = ["/usr/bin/makensis"] - elif os.path.exists("/usr/local/bin/makensis"): - makensis_cmd = ["/usr/local/bin/makensis"] - elif os.path.exists(r"C:\Program Files (x86)\NSIS\makensis.exe"): - makensis_cmd = [r"C:\Program Files (x86)\NSIS\makensis.exe"] - elif os.path.exists(r"C:\Program Files\NSIS\makensis.exe"): - makensis_cmd = [r"C:\Program Files\NSIS\makensis.exe"] - - if not makensis_cmd: + makensis_bin = ensure_makensis() + if not makensis_bin: print("[!] Note: NSIS compiler (makensis) not found in PATH or standard directories.") return False + makensis_cmd = [makensis_bin] compilation_dir = os.path.join(ROOT_DIR, "compilation") success = True for nsi in ["installer_client.nsi", "installer_server.nsi"]: @@ -288,6 +327,7 @@ def build_linux(): is_linux_host = platform.system() == "Linux" if is_linux_host: + ensure_libpython() try: linux_client_script = os.path.join(SRC_DIR, "Linux_Client.py") build_pyinstaller_binary(linux_client_script, "Linux_Client.bin")