CBuild
C++ build system with scripts written in c++
Loading...
Searching...
No Matches
CBuild.cpp
Go to the documentation of this file.
1
21// C++ libraries
22#include "fstream"
23#include "iostream"
24#include "random"
25#include "stdio.h"
26// Project headers
30#include "../../headers/map.hpp"
33/* CBuild.hpp */
34// CBuild::RType CBuild::parse(lib::map<std::string, std::string> *args, int
35// argc, char **argv) {
36// // Init registry
37// CBuild::Registry::init();
38// // Argument counters
39// int acnt = 0;
40// int pacnt = 0;
41// // Default return
42// CBuild::RType ret = CBuild::ERROR;
43// // Parse all command line arguments
44// for (int i = 1; i < argc; i++) {
45// std::string tmp = argv[i];
46// // Force, not use cache compilation
47// if (tmp == std::string("-f")) {
48// try {
49// args->push_back_check("force", "force");
50// } catch (std::exception &e) {
51// }
52// // Verbose flag
53// } else if (tmp == std::string("-v")) {
54// try {
55// args->push_back_check("out", "verbose");
56// } catch (std::exception &e) {
57// }
58// // Disabling output
59// } else if (tmp == std::string("--no-cli-out")) {
60// try {
61// args->push_back_check("out", "none");
62// } catch (std::exception &e) {
63// }
64// // Makefile gen
65// } else if (tmp == std::string("-gm")) {
66// try {
67// args->push_back_check("gen", "make");
68// } catch (std::exception &e) {
69// }
70// // Compil database (compile_command.json) gen
71// } else if (tmp == std::string("-gc")) {
72// try {
73// args->push_back_check("gen", "ccj");
74// } catch (std::exception &e) {
75// }
76// // Load deps
77// } else if (tmp == std::string("-ld")) {
78// ret = CBuild::RType::LOAD_DEPS;
79// i++;
80// // Load toolchain name and perform all checks
81// if (i < argc) {
82// tmp = argv[i];
83// if (tmp.at(0) == '-') {
84// CBuild::print("-ld <toolchain name>");
85// exit(0xFF);
86// } else {
87// try {
88// args->push_back_check("toolchain_id", tmp);
89// } catch (std::exception &e) {
90// }
91// }
92// } else {
93// CBuild::print("-ld <toolchain name>");
94// exit(0xFF);
95// }
96// // Compile
97// } else if (tmp == std::string("-b")) {
98// // We build now, not error
99// ret = CBuild::BUILD;
100// i++;
101// // Load toolchain name and perform all checks
102// if (i < argc) {
103// tmp = argv[i];
104// if (tmp.at(0) == '-') {
105// CBuild::print("-b <toolchain name>");
106// exit(0xFF);
107// } else {
108// try {
109// args->push_back_check("toolchain_id", tmp);
110// } catch (std::exception &e) {
111// }
112// }
113// } else {
114// CBuild::print("-b <toolchain name>");
115// exit(0xFF);
116// }
117// // Run
118// } else if (tmp == std::string("-r")) {
119// // Run now, not error
120// ret = CBuild::RUN;
121// i++;
122// // Load toolchain name and perform all checks
123// if (i < argc) {
124// tmp = argv[i];
125// if (tmp.at(0) == '-') {
126// CBuild::print("-r <toolchain name>");
127// exit(0xFF);
128// } else {
129// try {
130// args->push_back_check("toolchain_id", tmp);
131// } catch (std::exception &e) {
132// }
133// }
134// } else {
135// try {
136// args->push_back_check("toolchain_id", "CBuild_all");
137// } catch (std::exception &e) {
138// }
139// }
140// // Build and run
141// } else if (tmp == std::string("-br")) {
142// // Build and run now, not error
143// ret = CBuild::BUILD_RUN;
144// i++;
145// // Load toolchain name and perform all checks
146// if (i < argc) {
147// tmp = argv[i];
148// if (tmp.at(0) == '-') {
149// CBuild::print("-br <toolchain name>");
150// exit(0xFF);
151// } else {
152// try {
153// args->push_back_check("toolchain_id", tmp);
154// } catch (std::exception &e) {
155// }
156// }
157// } else {
158// CBuild::print("-br <toolchain name>");
159// exit(0xFF);
160// }
161// // Debug
162// } else if (tmp == std::string("-d")) {
163// // Debug now, not error
164// ret = CBuild::DEBUG;
165// i++;
166// // Load toolchain name and perform all checks
167// if (i < argc) {
168// tmp = argv[i];
169// if (tmp.at(0) == '-') {
170// CBuild::print("-d <toolchain name>");
171// exit(0xFF);
172// } else {
173// try {
174// args->push_back_check("toolchain_id", tmp);
175// } catch (std::exception &e) {
176// }
177// }
178// } else {
179// CBuild::print("-d <toolchain name>");
180// exit(0xFF);
181// }
182// // Cleran builded app
183// } else if (tmp == std::string("-c")) {
184// // Clear now, not error
185// ret = CBuild::CLEAR;
186// i++;
187// // Load toolchain name and perform all checks
188// if (i < argc) {
189// tmp = argv[i];
190// if (tmp.at(0) == '-') {
191// CBuild::print("-c <toolchain name>");
192// exit(0xFF);
193// } else {
194// try {
195// args->push_back_check("toolchain_id", tmp);
196// } catch (std::exception &e) {
197// }
198// }
199// } else {
200// CBuild::print("-c <toolchain name>");
201// exit(0xFF);
202// }
203// // Run task
204// } else if (tmp == std::string("-t")) {
205// // Run task (legacy TASK) now
206// ret = CBuild::TASK;
207// i++;
208// // Load toolchain name and perform all checks
209// if (i < argc) {
210// tmp = argv[i];
211// if (tmp.at(0) == '-') {
212// CBuild::print("-t <task name>");
213// exit(0xFF);
214// } else {
215// args->push_back_check("task_id", tmp);
216// }
217// } else {
218// CBuild::print("-t <task name>");
219// exit(0xFF);
220// }
221// // Add argument
222// } else if (tmp == std::string("-a")) {
223// i++;
224// // Load argument and perform some checks
225// if (i < argc) {
226// tmp = argv[i];
227// args->push_back("a" + std::to_string(acnt), tmp);
228// acnt++;
229// } else {
230// exit(0xFF);
231// }
232// // Program arguments
233// } else if (tmp == std::string("-pa")) {
234// i++;
235// // Load program argument and perform some checks
236// if (i < argc) {
237// tmp = argv[i];
238// args->push_back("pa" + std::to_string(pacnt), tmp);
239// pacnt++;
240// } else {
241// exit(0xFF);
242// }
243// // Rebuild of CBuild
244// } else if (tmp == std::string("--rebuild")) {
245// ret = CBuild::REBUILD;
246// // Init workspace
247// } else if (tmp == std::string("--init")) {
248// // Fresh start
249// args->clear();
250// // Load init task
251// args->push_back("task_id", "CBuild_init");
252// return CBuild::TASK;
253// // Get help message
254// } else if (tmp == std::string("--version")) {
255// // Fresh start
256// args->clear();
257// // Load init task
258// args->push_back("task_id", "CBuild_version");
259// return CBuild::TASK;
260// // Get help message
261// } else if ((tmp == std::string("--help")) || (tmp == std::string("-h")))
262// {
263// // Fresh start
264// args->clear();
265// // Load help task
266// args->push_back("task_id", "CBuild_help");
267// return CBuild::TASK;
268// // Parse user-defined keywords
269// } else {
270// auto keys = Registry::GetKeywordsList();
271// for (unsigned int i = 0; i < keys.size(); i++) {
272// if (tmp == keys.at(i).key) {
273// ret = CBuild::TASK;
274// args->push_back_check("task_id", keys.at(i).data);
275// }
276// }
277// }
278// }
279// return ret;
280// }
282 // Check if cache directory exists
284 // Create dir
286 }
287 // Check if copy cache dir exists
289 // Create dir
291 }
292 // Check if lib cache sir exists
294 // Create dir
296 }
297 // Check if lib headers cache sir exists
299 // Create dir
301 }
302 // Args
303 std::vector<std::string> pargs, ppargs;
304 bool force = false;
305 // Load args
306 for (unsigned int i = 0; i < args->size(); i++) {
307 auto elem = args->at(i);
308 try {
309 // Custom arg for CBuild, user-proccesed
310 if (elem.key.at(0) == 'a') {
311 pargs.push_back(elem.data);
312 // Custom arg for runned app, for -r and -br
313 } else if (elem.key.at(0) == 'p' && elem.key.at(1) == 'a') {
314 ppargs.push_back(elem.data);
315 // Force recompilation
316 } else if (elem.key == std::string("force")) {
317 force = true;
318 // Different output modes
319 } else if (elem.key == std::string("out")) {
320 // More verbose output, some debugging things included ;)
321 if (elem.data == std::string("verbose")) {
323 // No output at all, only produced by compiler
324 } else if (elem.data == std::string("none")) {
326 }
327 }
328 } catch (std::exception& e) {
329 }
330 }
331 // Setup generators
332 if (args->get_ptr("gen") != NULL) {
333 auto generator = CBuild::Registry::GetGenerator(*(args->get("gen")));
334 if (!generator->init()) {
335 generator->generate(mode, args, &pargs);
336 }
337 goto mode_end;
338 }
339 // Select mode
340 switch (mode) {
341 // Build and rebuild of script
342 case CBuild::REBUILD:
343 case CBuild::BUILD: {
344 if (*(args->get("toolchain_id")) == std::string("all")) {
345 CBuild::Registry::ToolchainAll(force, *(args->get("curr_path")), &pargs);
346 } else {
347 // Load toolchain
348 std::string id = *(args->get("toolchain_id"));
350 // Error
351 if (target == NULL) {
352 CBuild::printf(CBuild::RED, "Toolchain %s not found. Exiting...\n", id.c_str());
353 exit(0xFF);
354 }
355 // Call tolchain in build mode
356 target->call(&pargs, force);
357 }
358 } break;
359 // Build and run
360 case CBuild::BUILD_RUN: {
361 // Load toolchain
362 std::string id = *(args->get("toolchain_id"));
364 // Error
365 if (target == NULL) {
366 CBuild::printf(CBuild::RED, "Toolchain %s not found. Exiting...\n", id.c_str());
367 exit(0xFF);
368 }
369 // Run toolchain in build mode
370 target->call(&pargs, force);
371 // Run toolchain in run mode
372 target->run(&ppargs);
373 } break;
374 // Run
375 case CBuild::RUN: {
376 // Load toolchain
377 std::string id = *(args->get("toolchain_id"));
379 // Error
380 if (target == NULL) {
381 CBuild::printf(CBuild::RED, "Toolchain %s not found. Exiting...\n", id.c_str());
382 exit(0xFF);
383 }
384 // Run toolchain in run mode
385 target->run(&ppargs);
386 } break;
387 // Build and run indebug mode
388 case CBuild::DEBUG: {
389 // Load toolchain
390 std::string id = *(args->get("toolchain_id"));
392 // Error
393 if (target == NULL) {
394 CBuild::printf(CBuild::RED, "Toolchain %s not found. Exiting...\n", id.c_str());
395 exit(0xFF);
396 }
397 // Run toolchain in debug mode
398 target->debug(&pargs, &ppargs);
399 } break;
400 // Clear (files)
401 case CBuild::CLEAR: {
402 // Load toolchain
403 std::string id = *(args->get("toolchain_id"));
405 // Error
406 if (target == NULL) {
407 CBuild::printf(CBuild::RED, "Toolchain %s not found. Exiting...\n", id.c_str());
408 exit(0xFF);
409 }
410 // Run toolchain is self-clear mode
411 target->clear();
412 } break;
413 // Run task
414 case CBuild::TASK:
415 // Call task
416 CBuild::Registry::CallTask(*(args->get("task_id")), pargs);
417 break;
418 // Load deps
419 case CBuild::LOAD_DEPS: {
420 // Load toolchain
421 std::string id = *(args->get("toolchain_id"));
423 // Error
424 if (target == NULL) {
425 CBuild::printf(CBuild::RED, "Toolchain %s not found. Exiting...\n", id.c_str());
426 exit(0xFF);
427 }
428 // Load libs
429 target->load_project_deps(*(args->get("curr_path")));
430 } break;
431 // Error
432 case CBuild::ERROR:
433 [[fallthrough]];
434 // Also error ;)
435 default:
436 exit(0xFF);
437 }
438 if (args->get("gen") != NULL) {
439 auto generator = CBuild::Registry::GetGenerator(*(args->get("gen")));
440 generator->generate(mode, args, &pargs);
441 }
442mode_end:
443 // auto gen = args->get_ptr("gen");
444 // gen = NULL;
445 // // Wee need to generate Makefile
446 // if (gen != NULL && gen->data == std::string("make")) {
447 // // Wee need to generate compile_command.json
448 // } else if (gen != NULL && gen->data == std::string("ccj")) {
449 // // We can generate it only for compilation
450 // if (mode == CBuild::RUN || mode == CBuild::TASK || mode ==
451 // CBuild::CLEAR ||
452 // mode == CBuild::RType::REBUILD || mode == CBuild::RType::ERROR) {
453 // goto gen_end;
454 // }
455 // CBuild::print("Generating compile_commands.json ...",
456 // CBuild::color::MAGENTA);
457 // // Get command log
458 // auto log = CBuild::get_log();
459 // // Recreate file
460 // if (CBuild::fs::exists(CBUILD_COMPILE_COMMAND_JSON)) {
461 // CBuild::fs::remove(CBUILD_COMPILE_COMMAND_JSON, true);
462 // }
463 // CBuild::fs::create({CBUILD_COMPILE_COMMAND_JSON},
464 // CBuild::fs::type::FILE);
465 // // Open file
466 // std::ofstream ccj;
467 // ccj.open(CBUILD_COMPILE_COMMAND_JSON, std::ios::out);
468 // ccj << "[\n";
469 // // For every executed command
470 // bool first = true;
471 // for (unsigned int i = 0; i < log->size(); i++) {
472 // // Get line data
473 // std::string cmd = log->at(i);
474 // // Does it is compilation command
475 // std::regex
476 // pattern("(\\S+)\\s+-c\\s+(\\S+)\\s+(.*)\\s+-o\\s+(\\S+)",
477 // std::regex_constants::icase);
478 // if (std::regex_match(cmd, pattern)) {
479 // // Preload some data to .json
480 // if (first == false)
481 // ccj << ",\n";
482 // first = false;
483 // ccj << "{\n";
484 // // Get file name
485 // std::istringstream iss(cmd);
486 // std::string word;
487 // while (iss >> word) {
488 // std::regex file(".*\\.(cpp|cc|c|cxx)");
489 // if (std::regex_match(word, file)) {
490 // break;
491 // }
492 // }
493 // // Add \ for needed data
494 // std::string cmd_prep = "";
495 // std::ostringstream ss;
496 // for (char c : cmd) {
497 // switch (c) {
498 // case '\"':
499 // ss << "\\\"";
500 // break;
501 // case '\\':
502 // ss << "\\\\";
503 // break;
504 // case '/':
505 // ss << "\\/";
506 // break;
507 // case '\b':
508 // ss << "\\b";
509 // break;
510 // case '\f':
511 // ss << "\\f";
512 // break;
513 // case '\n':
514 // ss << "\\n";
515 // break;
516 // case '\r':
517 // ss << "\\r";
518 // break;
519 // case '\t':
520 // ss << "\\t";
521 // break;
522 // case '$':
523 // ss << "$";
524 // break;
525 // default:
526 // ss << c;
527 // break;
528 // }
529 // }
530 // // Other data, properly formatted
531 // cmd_prep = ss.str();
532 // ccj << "\t\"directory\": \"";
533 // ccj << args->get_ptr("curr_path")->data;
534 // ccj << "\",\n";
535 // ccj << "\t\"command\": \"";
536 // ccj << cmd_prep;
537 // ccj << "\",\n";
538 // ccj << "\t\"file\": \"";
539 // ccj << word;
540 // ccj << "\"\n";
541 // ccj << "}";
542 // }
543 // }
544 // ccj << "\n]\n";
545 // ccj.close();
546 // }
547 // gen_end:
548 return;
549}
550void CBuild::rebuild(std::string scripts) {
552 "Dont use this function direclty, simply call toolchain \"cbuild_rebuild_build_script\"",
554}
555namespace CBuild {
557} // namespace CBuild
559 return CBUILD_VERSION_STR;
560}
570std::string CBuild::get_random_string(unsigned int length) {
571 // Random string and uniform distribution, for generating char
572 const std::string characters =
573 "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_-";
574 std::uniform_int_distribution<> dis(0, characters.size() - 1);
575 // Random generator
576 std::mt19937_64 gen;
577#ifdef __linux__
578 // Open random device
579 std::ifstream urandom("/dev/urandom", std::ios::binary);
580 if (!urandom) {
581 goto pseudo;
582 }
583
584 // Get random data from /dev/urandom
585 std::random_device::result_type seed;
586 urandom.read(reinterpret_cast<char*>(&seed), sizeof(seed));
587
588 // Seed random generator
589 {
590 CBuild::print_full("Using /dev/urandom for seed", CBuild::MAGENTA);
591 std::seed_seq seedSeq{seed};
592 gen.seed(seedSeq);
593 goto gen;
594 }
595pseudo:
596#endif
597 // Seed random generator - fallback
598 {
599 CBuild::print_full("Using std::random_device for seed", CBuild::MAGENTA);
600 std::random_device rd;
601 gen.seed(rd());
602 }
603gen:
604 // Generate random string with specified length
605 std::string randomString;
606 for (unsigned int i = 0; i < length; ++i) {
607 randomString += characters[dis(gen)];
608 }
609 return randomString;
610}
Main headers of CBuild core.
#define CBUILD_PROJECT_DEPS_DIR
For other included project, in cache dir.
#define CBUILD_VERSION_MAJOR
Different representation of CBuild version.
#define CBUILD_VERSION_STR
#define CBUILD_COPY_CACHE_DIR
tmp dir in cache dir
#define CBUILD_CACHE_DIR
Cache directory of CBuild.
#define CBUILD_PROJECT_DEPS_HEADERS
For other included project, in cache dir.
#define CBUILD_VERSION_MINOR
Toolchain class.
Definition Build.hpp:65
virtual void clear()
Clear all caches and builded app.
Definition Build.cpp:723
virtual void load_project_deps(std::string curr_path)
Load all project dependencies.
Definition Build.cpp:478
virtual void debug(std::vector< std::string > *args, std::vector< std::string > *pargs)
Build program in debug mode and after run gdb on it.
Definition Build.cpp:698
virtual void run(std::vector< std::string > *args)
Run builded app.
Definition Build.cpp:677
virtual void call(std::vector< std::string > *args, bool force=false, bool debug=false, bool dummy=false)
Call tollchain to execute.
Definition Build.cpp:572
Simple map implementation with some stack operation added.
Definition map.hpp:79
__SIZE_TYPE__ size()
Size of map.
Definition map.hpp:275
const _D * get(_K key)
Get element by it's key.
Definition map.hpp:159
lib::mapData< _K, _D > at(__SIZE_TYPE__ i)
Array operation, get element at index.
Definition map.hpp:223
lib::mapData< _K, _D > * get_ptr(_K key)
Get reference to key and value of map.
Definition map.hpp:175
filesystem++ api
Custom implementation of map datatype.
CBuild::Toolchain * GetToolchain(std::string name, bool force=false)
Get the registered toolchain.
Definition register.cpp:239
void CallTask(std::string name, std::vector< std::string > args)
Run tasks.
Definition register.cpp:206
CBuild::generator_base * GetGenerator(std::string id)
Get generator for specified id.
Definition register.cpp:317
void ToolchainAll(bool force, std::string path, std::vector< std::string > *args)
Call and execute all toolchains.
Definition register.cpp:293
bool exists(std::string path)
Check if file exists.
bool create(std::vector< std::string > paths, CBuild::fs::type what)
Create element.
@ DIR
Alias for DIRECTORY.
Filebuffer for CBuild ecosystem.
Definition Build.hpp:34
void void void print_verbose()
Enable verbose flag.
Definition print.cpp:98
void print(std::string msg, color fg=CBuild::WHITE)
Print colored text to STDOUT.
Definition print.cpp:70
int version[]
Definition CBuild.cpp:556
@ RED
Definition print.hpp:34
@ MAGENTA
Definition print.hpp:38
std::string get_version_string()
Return version as string.
Definition CBuild.cpp:558
int * get_version_array()
Get full CBuild version as int array of two components, no oveflow or rewrite check !
Definition CBuild.cpp:567
int get_version_major()
Get major component of CBuild version.
Definition CBuild.cpp:561
void exit(int code)
RType
Run mode.
Definition CBuild.hpp:34
@ REBUILD
Rebuild user executable.
Definition CBuild.hpp:62
@ ERROR
Some error occurred.
Definition CBuild.hpp:70
@ DEBUG
Build and run target in debug mode.
Definition CBuild.hpp:54
@ RUN
Run target.
Definition CBuild.hpp:46
@ CLEAR
Clear build output and cache.
Definition CBuild.hpp:58
@ TASK
Run task.
Definition CBuild.hpp:38
@ BUILD_RUN
Build and run target.
Definition CBuild.hpp:50
@ LOAD_DEPS
Load other project deps.
Definition CBuild.hpp:66
@ BUILD
Build target.
Definition CBuild.hpp:42
void printf(color fg, const char *fmt,...) __attribute__((format(printf
Some poor printf implementation.
Definition print.cpp:80
int get_version_minor()
Get minor component of CBuild version.
Definition CBuild.cpp:564
std::string get_random_string(unsigned int length)
Generate random string with specified range, on Linux can use /dev/urandom.
Definition CBuild.cpp:570
void print_none()
Fully disable all print though CBuild::print.
Definition print.cpp:101
void print_full(std::string msg, color fg=CBuild::WHITE)
Print colored text to STDOUT if verbose flag is set.
Definition print.cpp:75
void loop(RType mode, lib::map< std::string, std::string > *args)
loop of CBuild
Definition CBuild.cpp:281
void rebuild(std::string scripts)
Rebuild userspace part of CBuild.
Definition CBuild.cpp:550
Custom print that support color codes.
Register any things.