commit d3525f66d4ee9dfc1bfbcba3122de7e195af911e Author: Timerix22 Date: Wed Jul 12 02:34:49 2023 +0600 proj file parsing diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b000471 --- /dev/null +++ b/.gitignore @@ -0,0 +1,12 @@ +bin/ +obj/ + +tmp/ +temp/ +*.tmp + +log/ +logs/ +*.log + +*.user diff --git a/.vscode/.gitignore b/.vscode/.gitignore new file mode 100644 index 0000000..c3d3a20 --- /dev/null +++ b/.vscode/.gitignore @@ -0,0 +1 @@ +settings.json \ No newline at end of file diff --git a/build.sh b/build.sh new file mode 100644 index 0000000..f497caf --- /dev/null +++ b/build.sh @@ -0,0 +1,31 @@ +#!/bin/bash +set -eo pipefail +CMP="gcc" +ARGS="-Wall -Wno-discarded-qualifiers -O2" +SRC="$(find . -name '*.c')" +LINK="-L. -lkerep" + +OS=$(./detect_os.sh) +ARCH=$(./detect_arch.sh) + +if [[ OS == "windows" ]]; then + OUT_FILE="cbuild.exe" +else + OUT_FILE="cbuild" +fi + +command="$CMP $ARGS + -DOS=$OS -DARCH=$ARCH +$SRC + $LINK + -o bin/$OUT_FILE" + +rm -rf bin +mkdir bin +echo "$command" + +tar xJf libkerep.a.tar.xz + +$($command) + +rm libkerep.a diff --git a/detect_arch.sh b/detect_arch.sh new file mode 100644 index 0000000..5779297 --- /dev/null +++ b/detect_arch.sh @@ -0,0 +1,23 @@ +#!/bin/bash +uname_rezult="$(uname -m)" + +case "$uname_rezult" in + arm | arm32 | armhf | aarch32) + ARCH=arm32 + ;; + arm64 | aarch64 | aarch64_be | armv8b | armv8l) + ARCH=arm64 + ;; + x86 | i386 | i486 | i686) + ARCH=x86 + ;; + x64 | x86_64 | amd64) + ARCH=x64 + ;; + *) + echo "unknown CPU architecture: $uname_rezult" + exit 1 + ;; +esac + +echo "\"$ARCH\"" diff --git a/detect_os.sh b/detect_os.sh new file mode 100644 index 0000000..673c5f7 --- /dev/null +++ b/detect_os.sh @@ -0,0 +1,26 @@ +#!/bin/bash +uname_rezult="$(uname -o)" + +case "$uname_rezult" in + Msys | Cygwin | "MS/Windows") + OS=windows + ;; + Linux | GNU/Linux) + OS=linux + ;; + Android) + OS=android; + ;; + FreeBSD) + OS=freebsd + ;; + Darwin) + OS=macos + ;; + *) + echo "unknown operating system: $uname_rezult" + exit 1 + ;; +esac + +echo "\"$OS\"" diff --git a/libkerep.a.tar.xz b/libkerep.a.tar.xz new file mode 100644 index 0000000..06af52d Binary files /dev/null and b/libkerep.a.tar.xz differ diff --git a/src/CompilationScenario.c b/src/CompilationScenario.c new file mode 100644 index 0000000..9a1364c --- /dev/null +++ b/src/CompilationScenario.c @@ -0,0 +1,103 @@ +#include "CompilationScenario.h" + +void CompilationScenario_construct(CompilationScenario* ptr){ + ptr->compiler = "UNDEFINED_COMPILER"; + ptr->obj_dir = "obj"; + ptr->out_dir = "bin"; + ptr->args_pre = Autoarr_create(Pointer, 32, 32); + ptr->sources = Autoarr_create(Pointer, 32, 32); + ptr->args_post = Autoarr_create(Pointer, 32, 32); + ptr->defines = Autoarr_create(Pointer, 32, 32); +} + +void CompilationScenario_destruct(CompilationScenario* ptr){ + Autoarr_freeWithoutMembers(ptr->args_pre, true); + Autoarr_freeWithoutMembers(ptr->sources, true); + Autoarr_freeWithoutMembers(ptr->args_post, true); + Autoarr_freeWithoutMembers(ptr->defines, true); +} + +#define Dtsod_setStrField(FIELD) \ + if(Hashtable_tryGet(dtsod, #FIELD, &val)){ \ + if(val.typeId != ktid_char_Ptr) \ + safethrow(#FIELD " value expected to be string",;);\ + sc->FIELD = val.VoidPtr; \ + } + +#define Dtsod_addArrField(FIELD, ELEM_TYPE) \ + if(Hashtable_tryGet(dtsod, #FIELD, &val)){ \ + if(val.typeId != ktid_Autoarr_Unitype_Ptr) \ + safethrow(#FIELD " value expected to be array", ;); \ + Autoarr(Unitype)* ar = val.VoidPtr; \ + Autoarr_foreach(ar, el, \ + if(el.typeId != ktid_ptrName(ELEM_TYPE)) \ + safethrow(#FIELD " array values expected to be " #ELEM_TYPE, ;); \ + Autoarr_add(sc->FIELD, el.VoidPtr); \ + ) \ + } + +Maybe CompilationScenario_tryApplyOptions(CompilationScenario* sc, Hashtable* dtsod){ + Unitype val = UniNull; + Dtsod_setStrField(compiler); + Dtsod_setStrField(obj_dir); + Dtsod_setStrField(out_dir); + Dtsod_addArrField(args_pre, char); + Dtsod_addArrField(sources, char); + Dtsod_addArrField(args_post, char); + Dtsod_addArrField(defines, char); + + try(CompilationScenario_tryApplyPlatformSpecificOptions(sc, dtsod), _m0, ;); + + return SUCCESS(UniBool(Unitype_isUniNull(val) || _m0.value.Bool)); +} + +Maybe CompilationScenario_tryApplyConditionalOptions(CompilationScenario* sc, Hashtable* dtsod, const char* condition_name){ + Unitype val = UniNull; + if(Hashtable_tryGet(dtsod, condition_name, &val)){ + if(val.typeId != ktid_Hashtable_Ptr) + safethrow(cptr_concat(condition_name, " expected to be key-value map"), ;); + Hashtable* conditional_options = val.VoidPtr; + try(CompilationScenario_tryApplyOptions(sc, conditional_options), _m0, ;); + return SUCCESS(UniTrue); + } + else return SUCCESS(UniFalse); +} + +Maybe CompilationScenario_tryApplyPlatformSpecificOptions(CompilationScenario* sc, Hashtable* dtsod){ + try(CompilationScenario_tryApplyConditionalOptions(sc, dtsod, os), _m0, ;); + try(CompilationScenario_tryApplyConditionalOptions(sc, dtsod, arch), _m1, ;); + + char* os_and_arch = cptr_concat(os, "-", arch); + try(CompilationScenario_tryApplyConditionalOptions(sc, dtsod, os_and_arch), _m2, ;); + free(os_and_arch); + + os_and_arch = cptr_concat(os, "_", arch); + try(CompilationScenario_tryApplyConditionalOptions(sc, dtsod, os_and_arch), _m3, ;); + free(os_and_arch); + + return SUCCESS(UniBool(_m0.value.Bool || _m1.value.Bool || _m2.value.Bool || _m3.value.Bool)); +} + +Maybe CompilationScenario_applyConfigurationOptions(CompilationScenario* sc, Hashtable* dtsod, const char* configuration){ + try(CompilationScenario_tryApplyConditionalOptions(sc, dtsod, configuration), _m0, ;); + if(!_m0.value.Bool) + safethrow(cptr_concat("configuration '", configuration, "' not found"), ;); + return MaybeNull; +} + +Maybe CompilationScenario_applyTaskOptions(CompilationScenario* sc, Hashtable* dtsod, const char* task){ + try(CompilationScenario_tryApplyConditionalOptions(sc, dtsod, task), _m0, ;); + if(!_m0.value.Bool) + safethrow(cptr_concat("task '", task, "' not found"), ;); + return MaybeNull; +} + +Maybe CompilationScenario_applyProjectOptions(CompilationScenario* sc, Hashtable* dtsod, const char* configuration, const char* task){ + // general options + try(CompilationScenario_tryApplyOptions(sc, dtsod), _m0, ;); + // configuration options + try(CompilationScenario_applyConfigurationOptions(sc, dtsod, configuration), _m1, ;); + // task options + try(CompilationScenario_applyTaskOptions(sc, dtsod, task), _m2, ;); + return MaybeNull; +} diff --git a/src/CompilationScenario.h b/src/CompilationScenario.h new file mode 100644 index 0000000..237f3ae --- /dev/null +++ b/src/CompilationScenario.h @@ -0,0 +1,43 @@ +#include "../../GraphC/dependencies/kerep/src/DtsodParser/DtsodV24.h" + +extern const char* os; +extern const char* arch; + +typedef struct { + const char* compiler; + const char* obj_dir; + const char* out_dir; + Autoarr(Pointer)* args_pre; + Autoarr(Pointer)* sources; + Autoarr(Pointer)* args_post; + Autoarr(Pointer)* defines; +} CompilationScenario; + +/* Public Functions */ + +void CompilationScenario_construct(CompilationScenario* ptr); + +void CompilationScenario_destruct(CompilationScenario* ptr); + +/// applies all options from project, selected configuration and task +///@return Maybe +Maybe CompilationScenario_applyProjectOptions(CompilationScenario* sc, Hashtable* dtsod, const char* configuration, const char* task); + + +/* Internal Functions */ + +///@return Maybe +Maybe CompilationScenario_tryApplyOptions(CompilationScenario* sc, Hashtable* dtsod); + +///@return Maybe +Maybe CompilationScenario_tryApplyConditionalOptions(CompilationScenario* sc, Hashtable* dtsod, const char* condition_name); + +/// tries to get options from dtsod fields named "windows", "linux", "android", "x64", "android-arm32", "windows_x86", etc. +///@return Maybe +Maybe CompilationScenario_tryApplyPlatformSpecificOptions(CompilationScenario* sc, Hashtable* dtsod); + +///@return Maybe +Maybe CompilationScenario_applyConfigurationOptions(CompilationScenario* sc, Hashtable* dtsod, const char* configuration); + +///@return Maybe +Maybe CompilationScenario_applyTaskOptions(CompilationScenario* sc, Hashtable* dtsod, const char* task); diff --git a/src/cbuilld.c b/src/cbuilld.c new file mode 100644 index 0000000..d212346 --- /dev/null +++ b/src/cbuilld.c @@ -0,0 +1,106 @@ +#include "../../GraphC/dependencies/kerep/src/base/base.h" +#include "../../GraphC/dependencies/kerep/src/Filesystem/filesystem.h" +#include "../../GraphC/dependencies/kerep/src/DtsodParser/DtsodV24.h" +#include "CompilationScenario.h" + +#ifndef OS +#define OS "UNDEFINED" +#endif +#ifndef ARCH +#define ARCH "UNDEFINED" +#endif + +const char* os=OS; +const char* arch=ARCH; + +const char* global_out_dir="bin"; +const char* configuration="release"; +const char* task="exe"; +const char** projects=NULL; +u16 project_count = 0; + +int erri(ErrorId err_code){ + throw(err_code); + return -1; +} + +#define argIs(STR) cptr_equals(arg, STR) +#define argNext() argv[++argi < argc ? argi : erri(ERR_WRONGINDEX)] + +char* projectFileFromDir(const char* dir){ + throw(ERR_NOTIMPLEMENTED); + // tryLast(dir_getFiles(dir, false), _m, ;); +} + +int main(const int argc, const char** argv){ + kt_beginInit(); + kt_initKerepTypes(); + kt_endInit(); + + if(cptr_equals(os, "UNDEFINED")) + throw("Operation system undefined. Recompile cbuild with flag -DOS=$(./detect_os.sh)"); + if(cptr_equals(arch, "UNDEFINED")) + throw("CPU architecture undefined. Recompile cbuild with flag -DARCH=$(./detect_arch.sh)"); + + Autoarr(Pointer)* projects_ar = Autoarr_create(Pointer, 16, 32); + + for(int argi = 1; argi < argc; argi++){ + const char* arg = argv[argi]; + kprintf("arg: %s\n", arg); + if(argIs("-h") || argIs("--help") || argIs("/?")) + kprintf("Usage: cbuild [options] [projects files/dirs]\n" + " Options:\n" + " -h, --help, /? Display this message.\n" + " -o, --out-dir Set global output directory (default=bin).\n" + " -c, --configuration Select project configuration (default=release).\n" + " -t, --task Select build task from project.\n"); + else if(argIs("-o") || argIs("--out-dir")) + global_out_dir = argNext(); + else if(argIs("-c") || argIs("--configuration")) + configuration = argNext(); + else if(argIs("-t") || argIs("--task")) + task = argNext(); + else { + if(arg[0] == '-') + throw(cptr_concat("invalid argument: ", arg)); + Autoarr_add(projects_ar, arg); + } + } + + project_count = Autoarr_length(projects_ar); + projects = (const char**)Autoarr_toArray(projects_ar); + Autoarr_freeWithoutMembers(projects_ar, true); + if(project_count == 0){ + projects = malloc(sizeof(char*)); + projects[0] = projectFileFromDir("."); + } + + for(u16 i=0; i < project_count; i++){ + const char* proj = projects[i]; + const char* proj_file_path = NULL; + if(file_exists(proj)) + proj_file_path = proj; + else if(dir_exists(proj)) + proj_file_path = projectFileFromDir(proj); + + tryLast(file_open(proj_file_path, FileOpenMode_Read), _m1, ;); + FileHandle proj_file = _m1.value.VoidPtr; + char* proj_file_text; + tryLast(file_readAll(proj_file, &proj_file_text), _m2, file_close(proj_file)); + file_close(proj_file); + + tryLast(DtsodV24_deserialize(proj_file_text), _m3, free(proj_file_text)); + Hashtable* proj_dtsod = _m3.value.VoidPtr; + CompilationScenario proj_sc; + CompilationScenario_construct(&proj_sc); + + tryLast(CompilationScenario_applyProjectOptions(&proj_sc, proj_dtsod, configuration, task), _m4, free(proj_file_text)) + + CompilationScenario_destruct(&proj_sc); + Hashtable_free(proj_dtsod); + free(proj_file_text); + } + + kt_free(); + return 0; +}