Move build and release tools (package_dist.py, upload_release.py, requirements.txt) into compilation/ directory
This commit is contained in:
@@ -0,0 +1,206 @@
|
||||
import os
|
||||
import sys
|
||||
import shutil
|
||||
import zipapp
|
||||
import hashlib
|
||||
import platform
|
||||
import subprocess
|
||||
import argparse
|
||||
|
||||
ROOT_DIR = os.path.abspath(os.path.dirname(__file__))
|
||||
SRC_DIR = os.path.join(ROOT_DIR, "src")
|
||||
DIST_DIR = os.path.abspath("dist")
|
||||
BUILD_TEMP = os.path.abspath("build_temp")
|
||||
|
||||
def clean_and_prep():
|
||||
if os.path.exists(DIST_DIR):
|
||||
shutil.rmtree(DIST_DIR)
|
||||
os.makedirs(DIST_DIR, exist_ok=True)
|
||||
if os.path.exists(BUILD_TEMP):
|
||||
shutil.rmtree(BUILD_TEMP)
|
||||
os.makedirs(BUILD_TEMP, exist_ok=True)
|
||||
|
||||
def build_pyinstaller_binary(script_path, binary_name):
|
||||
print(f"[*] Compiling {binary_name} with PyInstaller...")
|
||||
cmd = [
|
||||
sys.executable, "-m", "PyInstaller",
|
||||
"--onefile",
|
||||
"--clean",
|
||||
"--distpath", DIST_DIR,
|
||||
"--workpath", os.path.join(BUILD_TEMP, f"work_{binary_name}"),
|
||||
"--specpath", os.path.join(BUILD_TEMP, f"spec_{binary_name}"),
|
||||
"--name", binary_name,
|
||||
script_path
|
||||
]
|
||||
res = subprocess.run(cmd, capture_output=True, text=True)
|
||||
if res.returncode != 0:
|
||||
print(f"[!] Compilation error for {binary_name}:\n{res.stderr}")
|
||||
raise RuntimeError(f"Failed to build {binary_name}")
|
||||
print(f"[+] Successfully compiled {binary_name}")
|
||||
|
||||
def calculate_sha256(filepath):
|
||||
h = hashlib.sha256()
|
||||
with open(filepath, "rb") as f:
|
||||
while chunk := f.read(65536):
|
||||
h.update(chunk)
|
||||
return h.hexdigest()
|
||||
|
||||
def write_checksum_file(filename, digest, binary_filename):
|
||||
out_path = os.path.join(DIST_DIR, filename)
|
||||
with open(out_path, "w", encoding="utf-8") as f:
|
||||
f.write(f"{digest} {binary_filename}\n")
|
||||
print(f"[+] Generated checksum file: {filename} ({digest[:16]}...)")
|
||||
|
||||
def build_linux_zipapp_fallback():
|
||||
print("[*] Packaging Linux standalone zipapp fallback binaries...")
|
||||
# Linux Client zipapp
|
||||
app_dir = os.path.join(BUILD_TEMP, "linux_app")
|
||||
os.makedirs(app_dir, exist_ok=True)
|
||||
shutil.copy(os.path.join(SRC_DIR, "Linux_Client.py"), os.path.join(app_dir, "Linux_Client.py"))
|
||||
client_out = os.path.join(DIST_DIR, "Linux_Client.bin")
|
||||
zipapp.create_archive(
|
||||
source=app_dir,
|
||||
target=client_out,
|
||||
interpreter="/usr/bin/env python3",
|
||||
main="Linux_Client:main"
|
||||
)
|
||||
# Server zipapp
|
||||
srv_dir = os.path.join(BUILD_TEMP, "linux_srv")
|
||||
os.makedirs(srv_dir, exist_ok=True)
|
||||
shutil.copy(os.path.join(SRC_DIR, "Server.py"), os.path.join(srv_dir, "Server.py"))
|
||||
server_out = os.path.join(DIST_DIR, "Server.bin")
|
||||
zipapp.create_archive(
|
||||
source=srv_dir,
|
||||
target=server_out,
|
||||
interpreter="/usr/bin/env python3",
|
||||
main="Server:main"
|
||||
)
|
||||
|
||||
def build_windows():
|
||||
print("[*] Compiling Windows standalone executables...")
|
||||
win_client_script = os.path.join(SRC_DIR, "Win_Client.py")
|
||||
build_pyinstaller_binary(win_client_script, "Win_Client")
|
||||
|
||||
server_script = os.path.join(SRC_DIR, "Server.py")
|
||||
build_pyinstaller_binary(server_script, "Server")
|
||||
|
||||
client_bin = os.path.join(DIST_DIR, "Win_Client.exe")
|
||||
server_bin = os.path.join(DIST_DIR, "Server.exe")
|
||||
|
||||
sums = []
|
||||
if os.path.exists(client_bin):
|
||||
client_hash = calculate_sha256(client_bin)
|
||||
write_checksum_file("win_client_sha256sum", client_hash, "Win_Client.exe")
|
||||
write_checksum_file("win_agent_sha256sum", client_hash, "Win_Client.exe")
|
||||
sums.append(f"{client_hash} Win_Client.exe")
|
||||
else:
|
||||
print(f"[!] Warning: Expected {client_bin} was not found.")
|
||||
|
||||
if os.path.exists(server_bin):
|
||||
server_hash = calculate_sha256(server_bin)
|
||||
write_checksum_file("win_server_sha256sum", server_hash, "Server.exe")
|
||||
sums.append(f"{server_hash} Server.exe")
|
||||
else:
|
||||
print(f"[!] Warning: Expected {server_bin} was not found.")
|
||||
|
||||
sums_path = os.path.join(DIST_DIR, "SHA256SUMS_windows.txt")
|
||||
with open(sums_path, "w", encoding="utf-8") as f:
|
||||
f.write("\n".join(sums) + "\n")
|
||||
|
||||
def build_linux():
|
||||
print("[*] Compiling Linux standalone binaries...")
|
||||
is_linux_host = platform.system() == "Linux"
|
||||
|
||||
if is_linux_host:
|
||||
linux_client_script = os.path.join(SRC_DIR, "Linux_Client.py")
|
||||
build_pyinstaller_binary(linux_client_script, "Linux_Client.bin")
|
||||
|
||||
server_script = os.path.join(SRC_DIR, "Server.py")
|
||||
build_pyinstaller_binary(server_script, "Server.bin")
|
||||
|
||||
# Normalize extensions in case PyInstaller dropped .bin
|
||||
for name in ["Linux_Client", "Server"]:
|
||||
plain_path = os.path.join(DIST_DIR, name)
|
||||
bin_path = os.path.join(DIST_DIR, f"{name}.bin")
|
||||
if os.path.exists(plain_path) and not os.path.exists(bin_path):
|
||||
os.rename(plain_path, bin_path)
|
||||
|
||||
# Ensure executable permissions on Linux
|
||||
for b in ["Linux_Client.bin", "Server.bin"]:
|
||||
p = os.path.join(DIST_DIR, b)
|
||||
if os.path.exists(p):
|
||||
try:
|
||||
os.chmod(p, 0o755)
|
||||
except Exception:
|
||||
pass
|
||||
else:
|
||||
print("[!] Note: Host platform is not Linux. Generating executable zipapps for Linux target.")
|
||||
build_linux_zipapp_fallback()
|
||||
|
||||
client_bin = os.path.join(DIST_DIR, "Linux_Client.bin")
|
||||
server_bin = os.path.join(DIST_DIR, "Server.bin")
|
||||
|
||||
sums = []
|
||||
if os.path.exists(client_bin):
|
||||
client_hash = calculate_sha256(client_bin)
|
||||
write_checksum_file("linux_client_sha256sum", client_hash, "Linux_Client.bin")
|
||||
write_checksum_file("linux_agent_sha256sum", client_hash, "Linux_Client.bin")
|
||||
sums.append(f"{client_hash} Linux_Client.bin")
|
||||
else:
|
||||
print(f"[!] Warning: Expected {client_bin} was not found.")
|
||||
|
||||
if os.path.exists(server_bin):
|
||||
server_hash = calculate_sha256(server_bin)
|
||||
write_checksum_file("linux_server_sha256sum", server_hash, "Server.bin")
|
||||
sums.append(f"{server_hash} Server.bin")
|
||||
else:
|
||||
print(f"[!] Warning: Expected {server_bin} was not found.")
|
||||
|
||||
sums_path = os.path.join(DIST_DIR, "SHA256SUMS_linux.txt")
|
||||
with open(sums_path, "w", encoding="utf-8") as f:
|
||||
f.write("\n".join(sums) + "\n")
|
||||
|
||||
def main(target=None):
|
||||
if target is None:
|
||||
parser = argparse.ArgumentParser(description="LOGAR Standalone Binary Compiler & Packager")
|
||||
parser.add_argument(
|
||||
"--target", "-t",
|
||||
choices=["windows", "win", "linux", "auto"],
|
||||
default="auto",
|
||||
help="Target platform to compile binaries for (default: auto-detect)"
|
||||
)
|
||||
args, _ = parser.parse_known_args()
|
||||
target = args.target
|
||||
|
||||
if target == "auto":
|
||||
target = "windows" if platform.system() == "Windows" else "linux"
|
||||
elif target == "win":
|
||||
target = "windows"
|
||||
|
||||
print("=" * 60)
|
||||
print(" LOGAR Binary Packaging")
|
||||
print(f" Host Platform: {platform.system()} ({platform.machine()})")
|
||||
print(f" Target Platform: {target.upper()}")
|
||||
print("=" * 60)
|
||||
|
||||
clean_and_prep()
|
||||
|
||||
if target == "windows":
|
||||
build_windows()
|
||||
elif target == "linux":
|
||||
build_linux()
|
||||
else:
|
||||
raise ValueError(f"Unsupported target: {target}")
|
||||
|
||||
# Clean temporary build directory
|
||||
if os.path.exists(BUILD_TEMP):
|
||||
shutil.rmtree(BUILD_TEMP, ignore_errors=True)
|
||||
|
||||
print("\n[+] Binary shipping artifacts assembled in 'dist/':")
|
||||
for f in sorted(os.listdir(DIST_DIR)):
|
||||
sz = os.path.getsize(os.path.join(DIST_DIR, f))
|
||||
print(f" - {f} ({sz / (1024*1024):.2f} MB)" if sz > 1024*1024 else f" - {f} ({sz} bytes)")
|
||||
print("=" * 60)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user