CBuild basic classes
CBuild contains a few major parts: a CLI args parser + main loop, a registry + base classes and a few standard libs of CBuild.
The CLI args parser and main loop consists of, as described in name, of parser of useer provided console arguments and main CBuild loop that setup all environment and call user script. It supports adding environment variables for a call to every shell command(this is not target-specific or task-specific!). Also it supports adding new parse rules for a custom arguments encoding.
The registry includes some big tables and user-faced function to add object to this table (plus it's name) and get it back. Also there is some base classes:
-
CBuild::Task - simple task abstract class. Contains task id variable as std::string and dependency task list as std::vector<std::string>. Also it feathures function to get task id and dependency list and basic constructor that takes task id and dependency list as parameters.
-
CBuild::Toolchain - toolchain abstract class, based upon gcc syntax. It have many helper function for setting argument, managing internal things and other helper functions. Also it have seven function related to compilation: pre_build(), build(), post_build(), pre_link(), link(), link_pack()(for building .a files), post_link(). Also toolchain can depend on other toolchains, tasks and has many more internal things.
-
CBuild::generator_base - template used to generate Makefile and compile_commands.json. Not really documented. Use if you want to output some other build format or some strange thing ;).
-
CBuild::Hasher - base class to create a hashers and metadata store. They are baked into a toolchain instance.
Standard CBuild library includes:
-
lib::map - map datatype with very bad memory managment and preservertion of addition order, also it has ability to get element not only by it's id but by it's index.
-
lib::optional - optional datatypy. Represent value that can be not available.
-
CBuild::fs - easier to work with replacement for std::filesystem with some function, like path processing (from "../foo/bar" to "/home/user/foo/bar") and some other CBuild-specific functions. Also it feathures function to set a variable in file to some value (value is provided as std::string) and to replace some token in file by std::string.
-
CBuild::line_filebuff and CBuild::str_filebuff - two file buffering classes, provide full RAM-buffering of file and ability to acces file using char/line index and using char sequences.
-
CBuild::print... - a few print-related things, like colored print to the terminal.
-
CBuild::system and CBuild::system_piped - CBuild version of standard system() function and system() function that return shell output.
What CBuild does when user runs ./CBuild.run <some args>
Disclaimer: this section assumes that you don't modify main.cpp in scripts folder, that is provided by CBuild.
Firstly, code execution enters main() and then it runs user_init() function. It is a base of build-script. Then, when all user scripts is evalueated it creates lib::map<std::string, std::string> for storing user arguments after processing and then CBuild calls CBuild::parse function. This function return CBuild::RType(RunType) and aslo it takes pointer to lib::map created earlier, in function this map is populated with values. Then CBuild performs some checks - if RType is ERROR then CBuild exits. If user specifyes other run mode, than runtiime stores current path, obtained by std::string(std::filesystem::current_path().c_str()) to map with key "curr_path". Then CBuild core calls CBuild:loop() that preprocess all arguments, check run mode and run selected task, toolchain etc.
Build process overview
Disclaimer: this is based on CBuild:GXX toolchain implementation.
From the start, CBuild::Toolchain::call is called. We get args array pointer, and three booleans - are this compilation mode is force recompilation mode, are user is doing debug build or does this is a dummycall to resolve compilation args. Then CBuild core store these booleans and array to intenal variables and performs some checks. From the start CBuild::Toolchain::call checks if this target is dynamick library and if so, add -shared flag for linker. If debug build is specified, -g is added as compilation flag. Then, unconditionally -fPIC, -Icache/headers and -Lcache/libs is added. The we do toolchain init. This steps initializes directory structure for this target compilation. Then, if build type is dynamic library, runtime generates name of output binary, and add it as -Wl,-soname,<binary_name>. Then every dependancy task marked as PRE is called. Then every dependancy toolchain is called, all call arguments is passed from input argument to this call to CBuild::Toolchain::call, then we add so search pass and linker sear pass to find this dependancy library. Then pre_build, build, post_build and pre_link compilation steps are performed. These will be described later. Then, based on Build type we use standard linker to link object to binary, by calling link or use specific linker for packing static libraries by calling link_pack. And then last stepps of compilation - post_link is called! Now all that is left to do is to call all dependancy tasks, that is marked as POST and function can safely exits. Compilation is done!
build() This is toolchain implementation specific function, for CBuild::GXX it consists of: mergins compilation args list to one std::string, generating a list of files, that need to be recompiled using hasher and the constriction command to recompile each file in loop, for every file.
link() This is toolchain implementation specific function, for CBuild::GXX it consists of: merging linker args list to one std::string, getting list of object files in build/<toolchain_id>/objs/, merging this list to one std::string and then constring call to linker.
link_pack() This is toolchain implementation specific function, for CBuild::GXX it consists of: merging linker args list to one std::string, getting list of object files in build/<toolchain_id>/objs/, merging this list to one std::string and then constructing call to linker for static libraries (ar cr call).
Also, CBuild:GXX toolchain implementation unconditionally add this compilation and link arguments in it's constructor: -Wl,-z,origin and -Wl,-rpath,"\$ORIGIN".