Everything anyone should ever need to compile a C project should be a C compiler.
cbrew comes in two components:
- The
cbrewexecutable - The
cbrew.hheader
- Start by cloning this repository with the following command:
git clone https://github.com/Noxmor/cbrew- Run the
install.shscript. - Done!
- Start by cloning this repository with the following command:
git clone https://github.com/Noxmor/cbrew- Run the
install.batscript. - Update your
PATHenvironment variable to includeC:\cbrew\bin. - Update your compiler's include path environment variable (e.g.
C_INCLUDE_PATHforgcc) to includeC:\cbrew\include. - Done.
- Navigate into the root directory of your project
- Create a file named
cbrew.c. - Open
cbrew.cand start coding and customizing. See Examples for more information. - Done! You can now compile your project(s) by just running
cbrewinside the directory with thecbrew.cfile.
If you use cbrew in a git project, you should add the following to your .gitignore:
.cbrew/Note
Ideally, you would want to ignore your target directory and object directory as well. However, these are defined inside your cbrew.c file, so it's up to you to add the correct paths in your .gitignore.
With cbrew you can create projects and configurations that can than be automatically (re-)compiled. Every project has a unique name and a type. Every project needs to have at least one configuration that tells cbrew how to compile the project. Every configuration for a certain project has a unique name and more importantly a target directory and an object directory. The final product (depending on the type of the project) will be placed inside the target directory, while all object files will be placed inside the object directory. The cbrew executable automatically generates a local cbrew executable based on the cbrew.c file, which will be in charge of actually compiling your project(s). The local executable can be found at ./.cbrew/cbrew, relative to the location of the cbrew.c file.
Normally, you would need to recompile your local cbrew executable every time you make changes to the cbrew.c source file. This is tedious work that we want to avoid. Therefore, when you run cbrew it will automatically check if your local executable is outdated and if so, recompile it before executing it. If cbrew can't find an existing executable, it will automatically compile your cbrew.c file for the first time before executing it, thus bootstrapping it.
cbrew will detect your C compiler based on the CBREW_CC environment variable. If this variable is not set, cbrew will fallback to use gcc.
Whenever you're specifying a filepath e.g. foo/bar/buzz always use / as the path separator character. cbrew will automatically change the / character if your platform uses a different path separator.
Many internal functions of cbrew are filled with asserts to detect data that would result in a crash or undefined behaviour. If you're encountering weird behaviour of cbrew, try to enable asserts first and check if cbrew now raises any asserts. You can enable asserts by defining the CBREW_ENABLE_ASSERTS macro before including cbrew.h.
By default, cbrew logs everything in your standard console's text color. You can enable console colors by defining the CBREW_ENABLE_CONSOLE_COLORS macro before including cbrew.h. cbrew comes with a default set of colors, but if you don't like them, you can change them.
The logging colors that cbrew uses internally are:
CBREW_CONSOLE_COLOR_ERRORCBREW_CONSOLE_COLOR_WARNCBREW_CONSOLE_COLOR_INFOCBREW_CONSOLE_COLOR_TRACECBREW_CONSOLE_COLOR_COMMANDCBREW_CONSOLE_COLOR_PROJECTCBREW_CONSOLE_COLOR_CONFIGCBREW_CONSOLE_COLOR_TIME
If you want to change any of these colors, define the macro with any of cbrew's color macros before including cbrew.h.
The possible console colors are:
CBREW_CONSOLE_COLOR_BLACKCBREW_CONSOLE_COLOR_DARK_BLUECBREW_CONSOLE_COLOR_DARK_GREENCBREW_CONSOLE_COLOR_DARK_AQUACBREW_CONSOLE_COLOR_DARK_REDCBREW_CONSOLE_COLOR_DARK_PURPLECBREW_CONSOLE_COLOR_GOLDCBREW_CONSOLE_COLOR_GRAYCBREW_CONSOLE_COLOR_DARK_GRAYCBREW_CONSOLE_COLOR_BLUECBREW_CONSOLE_COLOR_GREENCBREW_CONSOLE_COLOR_AQUACBREW_CONSOLE_COLOR_REDCBREW_CONSOLE_COLOR_LIGHT_PURPLECBREW_CONSOLE_COLOR_YELLOWCBREW_CONSOLE_COLOR_WHITE
Example: Changing the default red color of error logs to white would look like this:
#define CBREW_CONSOLE_COLOR_ERROR CBREW_CONSOLE_COLOR_WHITEUnder the hood cbrew performs a variety of commands, so you don't have to manually type them in the console every time. By default, commands are not logged. If you want to have visual feedback on what cbrew does under the hood, you can define the CBREW_LOG_COMMANDS macro before including cbrew.h.
Inside cbrew.c:
#define CBREW_IMPLEMENTATION
#include <cbrew/cbrew.h>
int main(void)
{
CbrewProject* project = CBREW_PRJ_NEW("Hello-World", CBREW_PROJECT_TYPE_APP);
CBREW_PRJ_FILES(project, "./hello_world.c");
CbrewConfig* debug_config = CBREW_CFG_NEW(project, "Debug", "bin/Hello-World-Debug", "bin-int/Hello-World-Debug");
cbrew_build();
return 0;
}Inside cbrew.c:
#define CBREW_IMPLEMENTATION
#include <cbrew/cbrew.h>
int main(void)
{
CbrewProject* static_lib = CBREW_PRJ_NEW("Static-Libary-Name", CBREW_PROJECT_TYPE_STATIC_LIB);
CBREW_PRJ_FILES(static_lib, "./my_lib/**.c");
CbrewConfig* debug_config = CBREW_CFG_NEW(static_lib, "Debug", "bin/Static-Libary-Name-Debug", "bin-int/Static-Libary-Name-Debug");
cbrew_build();
return 0;
}Inside cbrew.c:
#define CBREW_IMPLEMENTATION
#include <cbrew/cbrew.h>
int main(void)
{
CbrewProject* dynamic_lib = CBREW_PRJ_NEW("Dynamic-Libary-Name", CBREW_PROJECT_TYPE_DYNAMIC_LIB);
CBREW_PRJ_FILES(dynamic_lib, "./my_lib/**.c");
CbrewConfig* debug_config = CBREW_CFG_NEW(dynamic_lib, "Debug", "bin/Dynamic-Libary-Name-Debug", "bin-int/Dynamic-Libary-Name-Debug");
cbrew_build();
return 0;
}Inside cbrew.c:
#define CBREW_IMPLEMENTATION
#include <cbrew/cbrew.h>
void create_foo_project(void)
{
CbrewProject* project = CBREW_PRJ_NEW("Foo", CBREW_PROJECT_TYPE_STATIC_LIB);
CBREW_PRJ_FILES(project, "./foo/**.c");
CBREW_PRJ_INCLUDE_DIR(project, "foo");
CBREW_PRJ_FLAG(project, "-Wall");
CBREW_PRJ_FLAG(project, "-Wextra");
CbrewConfig* debug_config = CBREW_CFG_NEW(project, "Debug", "bin/Foo-Debug", "bin-int/Foo-Debug");
CBREW_CFG_DEFINE(debug_config, "FOO_DEBUG");
CbrewConfig* release_config = CBREW_CFG_NEW(project, "Release", "bin/Foo-Release", "bin-int/Foo-Release");
CBREW_CFG_DEFINE(release_config, "FOO_RELEASE");
CBREW_CFG_FLAG(release_config, "-O3");
}
void create_bar_project(void)
{
CbrewProject* project = CBREW_PRJ_NEW("Bar", CBREW_PROJECT_TYPE_APP);
CBREW_PRJ_FILES(project, "./bar/**.c");
CBREW_PRJ_INCLUDE_DIR(project, "bar");
CBREW_PRJ_FLAG(project, "-Wall");
CBREW_PRJ_FLAG(project, "-Wextra");
CBREW_PRJ_LINK(project, "Foo.lib");
CbrewConfig* debug_config = CBREW_CFG_NEW(project, "Debug", "bin/Bar-Debug", "bin-int/Bar-Debug");
CBREW_CFG_DEFINE(debug_config, "BAR_DEBUG");
CbrewConfig* release_config = CBREW_CFG_NEW(project, "Release", "bin/Bar-Release", "bin-int/Bar-Release");
CBREW_CFG_DEFINE(release_config, "BAR_RELEASE");
CBREW_CFG_FLAG(release_config, "-O3");
}
int main(void)
{
create_foo_project();
create_bar_project();
cbrew_build();
return 0;
}