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 not os.path.isdir(build_dir): os.mkdir(build_dir) # 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) # generate doc files docs_folder = os.path.join(build_dir, "docs") if not os.path.isdir(docs_folder): os.mkdir(docs_folder) with open(os.path.join(docs_folder, "my_function.md"), "w") as f: f.write("# mylib_MyFunction\n") f.write("Describe your function briefly.\n\n") f.write("## Arguments\n") f.write("- myArgument (double): describe your arguments in a list format like this.\n\n") f.write("## Returns\n") f.write("result (int): then explain what the function returns\n\n") f.write("## Raises\n") f.write("- `ErrorName`: have your error reason here, include this if your function raises any errors\n") f.write("## Example\n") f.write("```python\n") f.write("# then show how you use the function in an example\n") f.write("call !mylib_MyFunction 123.0 &result\n") f.write("```\n") f.write("`Using \"python\" as the syntax highlighting language seems to work well with Ground.`") with open(os.path.join(build_dir, "SUMMARY.md"), "w") as f: f.write("# mylib\n") f.write("Introduce your module here!\n\nThis file will serve as an index page for all your docs.\n\n") f.write("## Subtitle (use this for categories)\n") f.write("- [mylib_MyFunction](docs/my_function.md)") console.print("[:white_check_mark:] Generated a new package for you!") shutil.move("main.so", os.path.join(build_dir, "main.so")) console.print("[:white_check_mark:] Put your library into your package!") 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!")