new project file structure

This commit is contained in:
Timerix22 2023-08-10 19:27:55 +03:00
parent a2fc40b006
commit 15085957fc
5 changed files with 197 additions and 63 deletions

78
TODO.md Normal file
View File

@ -0,0 +1,78 @@
## cbuild logic description
+ verify cbuild version
+ foreach dep in import
+ if dep starts with "./"
+ import local file
+ else
+ if find(dep in ./cbuild)
+ else if find (dep in global_config_dir/**)
+ else error: "import target 'dep' not found, try 'fluzm find dep'"
+ apply proj settings
+ apply platform settings
+ apply configuration settings
+ apply platform settings
+ foreach task in tasks
+ apply platform settings
+ foreach tool in tool_order
+ apply task settings
+ foreach src in find(dir, langs)
+ if platform, settings, src or src_deps (included headers) were changed
+ src -> src_to_process
+ if parallel
+ foreach src in src_to_process
+ run tool on src
+ else
+ run tool on src_to_process
+ copy files to general_out_dir
## Example of project.dtsod:
```yml
cbuild_version: 0;
import: [ "c", "c++", "gcc", "./some_local_file.dtsod" ];
gcc: {
src_languages: [ "c" ],
src_dirs: [ "src" ],
};
configurations: {
release: {
preprocess_sources: {
src_languages: [ "c", "c++" ],
src_dirs: [ "src" ],
},
gcc: {
pre_args: [ "-O2" ],
post_args: [ "-Wl,--gc-sections" ],
};
};
}
tasks: {
exe: {
pre_tasks: [ ],
tool_order: [ "preprocess_sources", "gcc", "g++", "g++-link" ],
g++: [ ... ],
};
};
languages: [
{
aliases: [ "c" ],
file_extensions: [ "c" ],
},
{
aliases: [ "c-header" ],
file_extensions: [ "h" ],
}
];
tools: [
{
aliases: [ "gcc" ],
exe_file: [ "gcc" ],
supported_languages: [ "c" ]; # set to "any" to use with any lang
parallel: true,
}
];
```

View File

@ -1,6 +1,7 @@
#!/bin/bash #!/bin/bash
set -eo pipefail set -eo pipefail
CONFIG_DIR="/etc/cbuild"
CMP="gcc" CMP="gcc"
WARN="-Wall -Wextra -Wno-discarded-qualifiers -Wno-unused-parameter" WARN="-Wall -Wextra -Wno-discarded-qualifiers -Wno-unused-parameter"
ARGS="-O2 -flto -fdata-sections -ffunction-sections -Wl,--gc-sections" ARGS="-O2 -flto -fdata-sections -ffunction-sections -Wl,--gc-sections"
@ -10,7 +11,7 @@ OS="$(./detect_os.sh)"
ARCH="$(./detect_arch.sh)" ARCH="$(./detect_arch.sh)"
LINK="-Lkerep/bin -lkerep-$OS-$ARCH" LINK="-Lkerep/bin -lkerep-$OS-$ARCH"
if [[ OS -eq "windows" ]]; then if [ "$OS" = "windows" ]; then
OUT_FILE="cbuild.exe" OUT_FILE="cbuild.exe"
else else
OUT_FILE="cbuild" OUT_FILE="cbuild"
@ -18,7 +19,7 @@ fi
command="$CMP $ARGS command="$CMP $ARGS
$WARN $WARN
-DOS=\"$OS\" -DARCH=\"$ARCH\" -DOS=\"$OS\" -DARCH=\"$ARCH\" -DCONFIG_DIR=\"$CONFIG_DIR\"
$SRC $SRC
$LINK $LINK
-o bin/$OUT_FILE" -o bin/$OUT_FILE"

View File

@ -1,47 +1,95 @@
#include <unistd.h>
#include "CompilationScenario.h" #include "CompilationScenario.h"
#include "unistd.h"
kt_define(Language, NULL, NULL);
Autoarr_define(Language, false);
kt_define(Tool, NULL, NULL);
kt_define(CompilationScenario, (freeMembers_t)CompilationScenario_destruct, NULL);
void CompilationScenario_construct(CompilationScenario* ptr){ void CompilationScenario_construct(CompilationScenario* ptr){
ptr->compiler = "UNDEFINED_COMPILER"; ptr->languages = Hashtable_create();
ptr->obj_dir = "obj"; ptr->tools = Hashtable_create();
ptr->out_file = "bin/out"; ptr->tool_order = Autoarr_create(Pointer, 32, 32);
ptr->args = Autoarr_create(Pointer, 32, 32);
ptr->sources = Autoarr_create(Pointer, 32, 32);
} }
void CompilationScenario_destruct(CompilationScenario* ptr){ void CompilationScenario_destruct(CompilationScenario* ptr){
Autoarr_freeWithoutMembers(ptr->args, true); // TODO
Autoarr_freeWithoutMembers(ptr->sources, true);
} }
#define Dtsod_setStrField(FIELD) \ void Tool_construct(Tool* ptr, Autoarr(Pointer)* aliases, const char* exe_file, bool parallel, Autoarr(Language)* supported_languages){
ptr->aliases = aliases;
ptr->exe_file = exe_file;
ptr->parallel = parallel;
ptr->supported_languages = Hashtable_create();
Autoarr_foreach(supported_languages, l,
Language* l_copy = malloc(sizeof(Language));
*l_copy = l;
Autoarr_foreach(l.aliases, l_name,
Hashtable_add(ptr->supported_languages, l_name, UniHeapPtr(Language, l_copy)));
)
ptr->src_languages = Hashtable_create();
ptr->src_dirs = Autoarr_create(Pointer, 32, 32);
ptr->pre_args = Autoarr_create(Pointer, 32, 32);
ptr->post_args = Autoarr_create(Pointer, 32, 32);
}
void Tool_destruct(Tool* ptr){
// TODO
}
#define Dtsod_getStrField(FIELD, OBJ) \
if(Hashtable_tryGet(dtsod, #FIELD, &val)){ \ if(Hashtable_tryGet(dtsod, #FIELD, &val)){ \
if(val.typeId != ktid_char_Ptr) \ if(val.typeId != ktid_char_Ptr) \
safethrow(#FIELD " value expected to be string",;);\ safethrow(#FIELD " value expected to be string",;);\
sc->FIELD = val.VoidPtr; \ OBJ->FIELD = val.VoidPtr; \
} }
#define Dtsod_addArrField(FIELD, ELEM_TYPE) \ #define Dtsod_addToStrAr(FIELD, OBJ) \
if(Hashtable_tryGet(dtsod, #FIELD, &val)){ \ if(Hashtable_tryGet(dtsod, #FIELD, &val)){ \
if(val.typeId != ktid_Autoarr_Unitype_Ptr) \ if(val.typeId != ktid_Autoarr_Unitype_Ptr) \
safethrow(#FIELD " value expected to be array", ;); \ safethrow(#FIELD " value expected to be a string array", ;); \
Autoarr(Unitype)* ar = val.VoidPtr; \ Autoarr(Unitype)* ar = val.VoidPtr; \
Autoarr_foreach(ar, el, \ Autoarr_foreach(ar, el, \
if(el.typeId != ktid_ptrName(ELEM_TYPE)) \ if(el.typeId != ktid_char_Ptr) \
safethrow(#FIELD " array values expected to be " #ELEM_TYPE, ;); \ safethrow(#FIELD " array values expected to be string", ;); \
Autoarr_add(sc->FIELD, el.VoidPtr); \ Autoarr_add(OBJ->FIELD, el.VoidPtr); \
) \ ) \
} }
Maybe CompilationScenario_tryApplyOptions(CompilationScenario* sc, Hashtable* dtsod){ Maybe Tool_tryApplyOptions(Tool* t, Hashtable* dtsod){
Unitype val = UniNull;
Dtsod_addToStrAr(src_dirs, t);
Dtsod_addToStrAr(pre_args, t);
Dtsod_addToStrAr(post_args, t);
if(Hashtable_tryGet(dtsod, "src_languages", &val)){ \
if(val.typeId != ktid_Autoarr_Unitype_Ptr) \
safethrow("src_languages value expected to be a string array", ;); \
Autoarr(Unitype)* ar = val.VoidPtr;
Autoarr_foreach(ar, el,
if(el.typeId != ktid_char_Ptr)
safethrow("src_languages array values expected to be string", ;);
const char* l_name = el.VoidPtr;
if(!Hashtable_tryGet(t->supported_languages, l_name, &val))
safethrow(cptr_concat("language '", l_name, "' isn't supported by tool '", Autoarr_get(t->aliases, 0), "'"), ;);
Hashtable_add(t->src_languages, l_name, val);
)
}
return MaybeNull;
}
Maybe CompilationScenario_tryApplyToolsOptions(CompilationScenario* sc, Hashtable* dtsod){
Unitype val = UniNull; Unitype val = UniNull;
Dtsod_setStrField(compiler);
Dtsod_setStrField(obj_dir);
Dtsod_setStrField(out_file);
Dtsod_addArrField(args, char);
Dtsod_addArrField(sources, char);
try(CompilationScenario_tryApplyPlatformSpecificOptions(sc, dtsod), _m0, ;); try(CompilationScenario_tryApplyPlatformSpecificOptions(sc, dtsod), _m0, ;);
Hashtable_foreach(sc->tools, _tool,
Tool* tool = _tool.value.VoidPtr;
if(Hashtable_tryGet(dtsod, _tool.key, &val)){
if(val.typeId != ktid_ptrName(Hashtable))
safethrow(ERR_WRONGTYPE, ;);
Hashtable* tool_dtsod = val.VoidPtr;
try(Tool_tryApplyOptions(tool, tool_dtsod), _m1, ;);
}
)
return SUCCESS(UniBool(Unitype_isUniNull(val) || _m0.value.Bool)); return SUCCESS(UniBool(Unitype_isUniNull(val) || _m0.value.Bool));
} }
@ -52,7 +100,7 @@ Maybe CompilationScenario_tryApplyConditionalOptions(CompilationScenario* sc, Ha
if(val.typeId != ktid_Hashtable_Ptr) if(val.typeId != ktid_Hashtable_Ptr)
safethrow(cptr_concat(condition_name, " expected to be key-value map"), ;); safethrow(cptr_concat(condition_name, " expected to be key-value map"), ;);
Hashtable* conditional_options = val.VoidPtr; Hashtable* conditional_options = val.VoidPtr;
try(CompilationScenario_tryApplyOptions(sc, conditional_options), _m0, ;); try(CompilationScenario_tryApplyToolsOptions(sc, conditional_options), _m0, ;);
return SUCCESS(UniTrue); return SUCCESS(UniTrue);
} }
else return SUCCESS(UniFalse); else return SUCCESS(UniFalse);
@ -77,6 +125,7 @@ Maybe CompilationScenario_applyConfigurationOptions(CompilationScenario* sc, Has
try(CompilationScenario_tryApplyConditionalOptions(sc, dtsod, configuration), _m0, ;); try(CompilationScenario_tryApplyConditionalOptions(sc, dtsod, configuration), _m0, ;);
if(!_m0.value.Bool) if(!_m0.value.Bool)
safethrow(cptr_concat("configuration '", configuration, "' not found"), ;); safethrow(cptr_concat("configuration '", configuration, "' not found"), ;);
return MaybeNull; return MaybeNull;
} }
@ -84,12 +133,17 @@ Maybe CompilationScenario_applyTaskOptions(CompilationScenario* sc, Hashtable* d
try(CompilationScenario_tryApplyConditionalOptions(sc, dtsod, task), _m0, ;); try(CompilationScenario_tryApplyConditionalOptions(sc, dtsod, task), _m0, ;);
if(!_m0.value.Bool) if(!_m0.value.Bool)
safethrow(cptr_concat("task '", task, "' not found"), ;); safethrow(cptr_concat("task '", task, "' not found"), ;);
return MaybeNull; return MaybeNull;
} }
Maybe CompilationScenario_applyProjectOptions(CompilationScenario* sc, Hashtable* dtsod, const char* configuration, const char* task){ Maybe CompilationScenario_applyProjectOptions(CompilationScenario* sc, Hashtable* dtsod, const char* configuration, const char* task){
// general options // TODO version check
try(CompilationScenario_tryApplyOptions(sc, dtsod), _m0, ;); // TODO import
// TODO register tools
// TODO register languagess
// project-wide options
try(CompilationScenario_tryApplyToolsOptions(sc, dtsod), _m0, ;);
// configuration options // configuration options
try(CompilationScenario_applyConfigurationOptions(sc, dtsod, configuration), _m1, ;); try(CompilationScenario_applyConfigurationOptions(sc, dtsod, configuration), _m1, ;);
// task options // task options
@ -97,25 +151,6 @@ Maybe CompilationScenario_applyProjectOptions(CompilationScenario* sc, Hashtable
return MaybeNull; return MaybeNull;
} }
/*
universal compilation:
pre-compilation tools
parallel foreach src
apply proj settings
apply lang settings
apply dir settings
if platform, settings or src were changed
compile object to onj/lang
concurrent add obj to obj_ar
post-compilation tools
example: if linkage enabled
apply proj linker settings
link
post-link tools
move files to general_out_dir
*/
Maybe CompilationScenario_exec(CompilationScenario* sc){ Maybe CompilationScenario_exec(CompilationScenario* sc){
/*const char ** compiler_args; /*const char ** compiler_args;
Autoarr_foreach(sc->sources, arg, Autoarr_foreach(sc->sources, arg,

View File

@ -3,14 +3,28 @@
extern const char* os; extern const char* os;
extern const char* arch; extern const char* arch;
typedef struct { STRUCT(Language,
const char* language; Autoarr(Pointer)* aliases;
const char* compiler; Autoarr(Pointer)* file_extensions;
const char* obj_dir; )
const char* out_file; Autoarr_declare(Language)
Autoarr(Pointer)* args;
Autoarr(Pointer)* sources; STRUCT(Tool,
} CompilationScenario; Autoarr(Pointer)* aliases;
const char* exe_file;
bool parallel;
Hashtable* supported_languages;
Hashtable* src_languages;
Autoarr(Pointer)* src_dirs;
Autoarr(Pointer)* pre_args;
Autoarr(Pointer)* post_args;
)
STRUCT(CompilationScenario,
Hashtable* tools; /* Hashtable<Tool> */
Hashtable* languages; /* Hashtable<Languages> */
Autoarr(Pointer)* tool_order;
)
/* Public Functions */ /* Public Functions */
@ -29,13 +43,15 @@ Maybe CompilationScenario_exec(CompilationScenario* sc);
/* Internal Functions */ /* Internal Functions */
/// tries to set options for tools registered in the project
///@return Maybe<bool> ///@return Maybe<bool>
Maybe CompilationScenario_tryApplyOptions(CompilationScenario* sc, Hashtable* dtsod); Maybe CompilationScenario_tryApplyToolsOptions(CompilationScenario* sc, Hashtable* dtsod);
/// tries to get any options from field <condition_name>
///@return Maybe<bool> ///@return Maybe<bool>
Maybe CompilationScenario_tryApplyConditionalOptions(CompilationScenario* sc, Hashtable* dtsod, const char* condition_name); 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. /// tries to get options from dtsod fields named "windowss", "linux", "android", "x64", "android-arm32", "windows_x86", etc.
///@return Maybe<bool> ///@return Maybe<bool>
Maybe CompilationScenario_tryApplyPlatformSpecificOptions(CompilationScenario* sc, Hashtable* dtsod); Maybe CompilationScenario_tryApplyPlatformSpecificOptions(CompilationScenario* sc, Hashtable* dtsod);

View File

@ -4,16 +4,21 @@
#include "CompilationScenario.h" #include "CompilationScenario.h"
#ifndef OS #ifndef OS
#error undefined OS
#define OS "UNDEFINED" #define OS "UNDEFINED"
#endif #endif
#ifndef ARCH #ifndef ARCH
#error undefined ARCH
#define ARCH "UNDEFINED" #define ARCH "UNDEFINED"
#endif #endif
#ifndef CONFIG_DIR
#error undefined CONFIG_DIR
#define CONFIG_DIR "UNDEFINED"
#endif
const char* os=OS; const char* os=OS;
const char* arch=ARCH; const char* arch=ARCH;
const char* global_config_dir=CONFIG_DIR;
const char* global_out_dir="bin";
const char* configuration="release"; const char* configuration="release";
const char* project_dir_or_file="./"; const char* project_dir_or_file="./";
Autoarr(Pointer)* tasks; Autoarr(Pointer)* tasks;
@ -39,9 +44,11 @@ int main(const int argc, const char** argv){
tasks = Autoarr_create(Pointer, 16, 32); tasks = Autoarr_create(Pointer, 16, 32);
if(cptr_equals(os, "UNDEFINED")) if(cptr_equals(os, "UNDEFINED"))
throw("Operation system undefined. Recompile cbuild with flag -DOS=\\\"$(./detect_os.sh)\\\""); throw("Undefined operation system. Recompile cbuild with flag -DOS=\\\"$(./detect_os.sh)\\\"");
if(cptr_equals(arch, "UNDEFINED")) if(cptr_equals(arch, "UNDEFINED"))
throw("CPU architecture undefined. Recompile cbuild with flag -DARCH=\\\"$(./detect_arch.sh)\\\""); throw("Undefined CPU architecture. Recompile cbuild with flag -DARCH=\\\"$(./detect_arch.sh)\\\"");
if(cptr_equals(global_config_dir, "UNDEFINED"))
throw("Undefined global config directory. Recompile cbuild with flag -DCONFIG_DIR=\\\"/etc/cbuild\\\"");
for(int argi = 1; argi < argc; argi++){ for(int argi = 1; argi < argc; argi++){
const char* arg = argv[argi]; const char* arg = argv[argi];
@ -50,13 +57,10 @@ int main(const int argc, const char** argv){
kprintf("Usage: cbuild [options] [tasks0 task1...]\n" kprintf("Usage: cbuild [options] [tasks0 task1...]\n"
" Options:\n" " Options:\n"
" -h, --help, /? Display this message.\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" " -c, --configuration Select project configuration (default=release).\n"
" -p, --project Set project directory/file (default=./).\n"); " -p, --project Set project directory/file (default=./).\n");
return 0; return 0;
} }
else if(argIs("-o") || argIs("--out-dir"))
global_out_dir = argNext();
else if(argIs("-c") || argIs("--configuration")) else if(argIs("-c") || argIs("--configuration"))
configuration = argNext(); configuration = argNext();
else if(argIs("-p") || argIs("--project")) else if(argIs("-p") || argIs("--project"))