added the build command

This commit is contained in:
2026-01-20 07:47:15 +11:00
parent 77a7a44804
commit a12990ef65
5 changed files with 109 additions and 5 deletions

95
src/build.py Normal file
View File

@@ -0,0 +1,95 @@
from util import *
import shutil
import os, sys
import subprocess
import configparser
from rich.console import Console
console = Console()
def find_c_files(path: str):
paths = []
for entry in os.listdir(path):
full_path = os.path.join(path, entry)
if os.path.isdir(full_path):
list_files_recursive(full_path)
else:
if full_path.endswith(".c"):
paths.append(full_path)
return paths
def build_mineral(args):
# sanity checks
if not os.path.isdir(args.folder_path):
console.print("[b red]digpkg: failed to build mineral: specified folder doesn't exist![/]")
sys.exit(1)
if not shutil.which("gcc"):
console.print("[b red]digpkg: failed to build mineral: gcc was not found![/]")
sys.exit(1)
# use gcc to compile the mineral
with console.status("Compiling", spinner="bouncingBall", spinner_style="green") as status:
c_files = find_c_files(args.folder_path)
if subprocess.run([
"gcc",
"-shared",
"-fPIC",
*c_files,
*[f"-{arg}" for arg in (args.gcc_args or [])],
"-o",
"main.so"
], stdout=None).returncode:
console.print("[b red]digpkg: failed to build mineral: gcc exited with non-zero exit code.[/]")
sys.exit(1)
console.print("[:white_check_mark:] Compile success!")
def build(args):
if args.package:
# build the mineral
build_mineral(args)
# create the build dir and throw in the .so file
with console.status("Packaging...", spinner="bouncingBall", spinner_style="green"):
build_dir = f"{os.path.basename(args.folder_path)}_build"
if os.path.isdir(build_dir):
shutil.rmtree(build_dir)
os.mkdir(build_dir)
shutil.move("main.so", os.path.join(build_dir, "main.so"))
# generate a mineral.ini file
config_parser = configparser.ConfigParser()
config_parser["package"] = {
"description": "Your description here",
"version": "1.0.0",
"config_version": "1"
}
config_parser["dependencies"] = {}
# write it to our new mineral
with open(os.path.join(build_dir, "mineral.ini"), "w") as f:
config_parser.write(f)
console.print("[:white_check_mark:] Packaged!")
console.print("\n[b cyan]note:[/] You will need to edit the [i]mineral.ini[/] file to make sure the version number and dependencies are correct.")
else:
check_sudo()
check_ground_libs_path()
# build the mineral and move it straight to the ground libs folder
build_mineral(args)
with console.status("Installing...", spinner="bouncingBall", spinner_style="green"):
shutil.move("main.so", os.path.join(os.getenv("GROUND_LIBS"), f"{os.path.basename(args.folder_path)}.so"))
console.print("[:white_check_mark:] Installed!")

View File

@@ -6,6 +6,7 @@ from publish import publish
from remove import remove from remove import remove
from list import list_cmd from list import list_cmd
from uninstall import uninstall from uninstall import uninstall
from build import build
def parse_arguments(): def parse_arguments():
@@ -34,8 +35,14 @@ def parse_arguments():
remove_command = sub_parsers.add_parser(name="remove", description="remove a published package from the repository") remove_command = sub_parsers.add_parser(name="remove", description="remove a published package from the repository")
remove_command.add_argument("name", help="name and version of the package") remove_command.add_argument("name", help="name and version of the package")
# env command # build command
build_command = sub_parsers.add_parser(name="build", description="build a folder as a mineral and either install it or prepare it for publishing")
build_command.add_argument("folder_path", help="path to the folder to build")
build_command.add_argument("--gcc-args", nargs="*", help="any extra args you want to give to gcc")
build_command.add_argument("--package", action="store_true", help="generate a folder with a mineral.ini and all the other files you need to publish the package")
# parse arguments are run the command we chose
args = arg_parser.parse_args() args = arg_parser.parse_args()
if not args.command: if not args.command:
@@ -52,6 +59,8 @@ def parse_arguments():
list_cmd(args) list_cmd(args)
elif args.command == "uninstall": elif args.command == "uninstall":
uninstall(args) uninstall(args)
elif args.command == "build":
build(args)
def main(): def main():
parse_arguments() parse_arguments()

View File

@@ -53,7 +53,7 @@ def publish(args):
sys.exit(1) sys.exit(1)
# compress to a tar file # compress to a tar file
console.status("Compressing") console.status("Compressing", spinner_style="green")
f = tempfile.TemporaryFile(mode="wb+") f = tempfile.TemporaryFile(mode="wb+")
with tarfile.open(fileobj=f, mode="w:gz") as tar_file: with tarfile.open(fileobj=f, mode="w:gz") as tar_file:
tar_file.add(args.folder_path, arcname=os.path.basename(args.folder_path)) tar_file.add(args.folder_path, arcname=os.path.basename(args.folder_path))
@@ -63,7 +63,7 @@ def publish(args):
console.print("[d][:white_check_mark:] Compressed![/]") console.print("[d][:white_check_mark:] Compressed![/]")
# send the request # send the request
status.update("Uploading...") status.update("Uploading...", spinner_style="blue")
response = requests.put( response = requests.put(
url=f"https://chookspace.com/api/packages/ground/generic/{mineral_name}/{version}/mineral.tar", url=f"https://chookspace.com/api/packages/ground/generic/{mineral_name}/{version}/mineral.tar",
data=f, data=f,

View File

@@ -12,7 +12,7 @@ def uninstall(args):
check_sudo() check_sudo()
check_ground_libs_path() check_ground_libs_path()
with console.status(status=f"Looking for [i]{args.name}[/]...", spinner="bouncingBall", spinner_style="blue") as status: with console.status(status=f"Looking for [i]{args.name}[/]...", spinner="bouncingBall", spinner_style="green") as status:
mineral_path = os.path.join(os.getenv("GROUND_LIBS"), args.name) mineral_path = os.path.join(os.getenv("GROUND_LIBS"), args.name)
symlink_path = os.path.join(os.getenv("GROUND_LIBS"), f"{args.name}.so") symlink_path = os.path.join(os.getenv("GROUND_LIBS"), f"{args.name}.so")

View File

@@ -6,7 +6,7 @@ from rich import print
def check_ground_libs_path(): def check_ground_libs_path():
# ensure the GROUND_LIBS var is set # ensure the GROUND_LIBS var is set
if not os.getenv("GROUND_LIBS"): if not os.getenv("GROUND_LIBS"):
print("digpkg: the [i]GROUND_LIBS[/] environment variable is not set, defaulting to /usr/lib/ground/") print("[d]digpkg: the [i]GROUND_LIBS[/] environment variable is not set, defaulting to /usr/lib/ground/")
os.environ["GROUND_LIBS"] = "/usr/lib/ground/" os.environ["GROUND_LIBS"] = "/usr/lib/ground/"
def check_sudo(): def check_sudo():