From 3ef10c07cfe013acf7456a147def4b0e112a2612 Mon Sep 17 00:00:00 2001 From: Radiquum Date: Mon, 5 May 2025 03:14:05 +0500 Subject: [PATCH] feat: add one-file build --- build.py | 49 +++++++++++++++++++++++++++++++++++++++--- requirements.build.txt | 1 + requirements.dev.txt | 1 + requirements.txt | 1 - src/main.py | 30 ++++++++++++++++++++------ 5 files changed, 71 insertions(+), 11 deletions(-) create mode 100644 requirements.build.txt create mode 100644 requirements.dev.txt diff --git a/build.py b/build.py index d5ef473..c585769 100644 --- a/build.py +++ b/build.py @@ -12,7 +12,12 @@ parser = argparse.ArgumentParser( description="Create and Download mod packs with ease", epilog="", ) -parser.add_argument("--no-rebuild", help="don't rebuild Next.js gui", action="store_true", default=False) +parser.add_argument( + "--no-rebuild", help="don't rebuild Next.js frontend", action="store_true", default=False +) +parser.add_argument( + "--exe", help="create an executable file", action="store_true", default=False +) if __name__ == "__main__": @@ -63,5 +68,43 @@ if __name__ == "__main__": print(f"Copied app: './src' -> '{OUT_DIR}'") shutil.copytree("./src", f"{OUT_DIR}/", dirs_exist_ok=True) - if os.path.exists(f"{OUT_DIR}/__pycache__") and os.path.isdir(f"{OUT_DIR}/__pycache__"): - shutil.rmtree(f"{OUT_DIR}/__pycache__") + print( + f"Copied requirements.txt: './requirements.txt' -> '{OUT_DIR}/requirements.txt'" + ) + shutil.copyfile(f"./requirements.txt", f"{OUT_DIR}/requirements.txt") + + if args.exe: + build = subprocess.call( + [ + "pyinstaller", + "main.py", + "-F", + "--add-data", + "static:static", + "--add-data", + "templates:templates", + ], + cwd="./dist", + shell=True, + ) + if build != 0: + print("[ERROR] pyinstaller has failed to build an app") + raise + + if os.path.exists(f"{OUT_DIR}/dist/main.exe"): + shutil.move(f"{OUT_DIR}/dist/main.exe", f"{OUT_DIR}/yamcpack.exe") + elif os.path.exists(f"{OUT_DIR}/dist/main"): + shutil.move(f"{OUT_DIR}/dist/main", f"{OUT_DIR}/yamcpack") + else: + print("[ERROR] no executable found") + raise + + print("cleanup...") + shutil.rmtree(f"{OUT_DIR}/dist") + shutil.rmtree(f"{OUT_DIR}/build") + os.remove(f"{OUT_DIR}/main.spec") + + if os.path.exists(f"{OUT_DIR}/__pycache__") and os.path.isdir( + f"{OUT_DIR}/__pycache__" + ): + shutil.rmtree(f"{OUT_DIR}/__pycache__") \ No newline at end of file diff --git a/requirements.build.txt b/requirements.build.txt new file mode 100644 index 0000000..ef376ca --- /dev/null +++ b/requirements.build.txt @@ -0,0 +1 @@ +pyinstaller diff --git a/requirements.dev.txt b/requirements.dev.txt new file mode 100644 index 0000000..a96ce29 --- /dev/null +++ b/requirements.dev.txt @@ -0,0 +1 @@ +flask-cors \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index 81affc9..d81b154 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,4 +3,3 @@ flaskwebgui requests Pillow flask-socketio -flask-cors \ No newline at end of file diff --git a/src/main.py b/src/main.py index 3104291..a5c42d2 100644 --- a/src/main.py +++ b/src/main.py @@ -1,14 +1,30 @@ from flask import Flask -from flask import render_template, redirect, url_for, send_file, abort +from flask import render_template, send_file, abort from flaskwebgui import FlaskUI # import FlaskUI import os -from flask_cors import CORS +import sys + from api import api -app = Flask(__name__) + +def resource_path(relative_path): + if hasattr(sys, "_MEIPASS"): + return os.path.join(sys._MEIPASS, relative_path) + return os.path.join(os.path.abspath("."), relative_path) + + +app = Flask( + __name__, + static_folder=resource_path("static"), + template_folder=resource_path("templates"), +) + + app.register_blueprint(api) -CORS(app, resources={r"/*": {"origins": "*"}}) +if os.getenv("is_dev") == "True": + from flask_cors import CORS + CORS(app, resources={r"/*": {"origins": "*"}}) @app.route("/") @@ -18,9 +34,9 @@ def index(): @app.route("/") def rewrite_next(path): - if os.path.exists(f"./static/{path}"): - return send_file(f"./static/{path}") - if os.path.exists(f"./templates/{path}.html"): + if os.path.exists(f"{resource_path("static")}/{path}"): + return send_file(f"{resource_path("static")}/{path}") + if os.path.exists(f"{resource_path("templates")}/{path}.html"): return render_template(f"{path}.html") return abort(404)