Skip to content

2am Build system - A single-header C build. No dependencies.

License

Notifications You must be signed in to change notification settings

kunyukzz/2am-builder

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

16 Commits
 
 
 
 
 
 
 
 

Repository files navigation

2AM Build System

A C based build system for when it's 2AM and you just want things to compile.

Built originally to compile my own game engine. Somehow can handle complex directory structures now. There is some limitation, maximum .c files per build only 256. And only work for UNIX-based system (although i haven't tested it on macOS & BSD).

2am-builder.h - A single-header C build system that builds your project by compiling it first.

Perfect For:

  • Weekend C projects
  • Learning C builds
  • Simple tools & utilities
  • School assignments
  • When other build tools feels like overkill (or confusing to setup)

Features:

  • Single-header (one dependency: libc)
  • Incremental compilation (only recompiles changed files)
  • Dependency tracking (.d files, Make-style)
  • System library & custom library linking
  • Mirror source directory structure
  • Can handle complex builds (I think)
  • Generate compilation database (.json) for clangd
  • Deploy prebuilt library to install on system (or local project directory)

Note: By default, 2am-builder mirrors your source structure. Call AM_SET_OBJECT_LAYOUT(AM_FLAT) before AM_BUILD if you prefer all object files in a single directory.


Important Note (Read This)

2am-builder.h must live in the project root directory.

DO NOT put it in src/, include/, tools/, or anywhere “cleaner”. The build system assumes all paths are relative to the project root.

If you move it:

  • files won’t be found
  • outputs will appear in strange places
  • reality will feel unstable

Cheatsheet

typedef enum {
    AM_MIRROR,
    AM_FLAT,
} object_layout_t;

typedef enum {
    BUILD_EXE,
    BUILD_SHARED,
    BUILD_STATIC
} build_type_t;

void AM_INIT(void);
void AM_RESET(void);

// Compiler setup 
void AM_SET_COMPILER(const char *compiler, const char *c_version);
void AM_SET_COMPILER_WARN(const char *warning);

// Source target setup 
void AM_SET_TARGET_DIRS(const char *binary_path, const char *object_path);
void AM_SET_TARGET_NAME(const char *target_name);

// Flag & linker setup 
void AM_SET_FLAGS(const char *flags);
void AM_ADD_LINKER_FLAGS(const char *linker_flags);

// Directory include
void AM_ADD_INCLUDE(const char *include_dir);

// Source selection
void AM_SET_SOURCE_ALL(const char *path);
void AM_SET_SOURCE_SPECIFIC(const char *path, const char **files);
void AM_SET_SOURCE_WITH_EXCLUDE(const char *base_path,
                                const char *exclude_path);

// Library linking
void AM_USE_PREBUILT_LIB(const char *lib_name, const char *lib_path);
void AM_USE_LIB(const char *lib_name);

// Build & compile
void AM_BUILD(build_type_t type, bool use_dependency);

// Additonal Features
void AM_GEN_DATABASE(void);
void AM_PREBUILT_TO_SYSTEM(bool system_mode, const char *library_path,
                           const char *header_path, bool has_headers);
void AM_SET_OBJECT_LAYOUT(object_layout_t);

Usage

  1. Copy 2am-builder.h to your project.
  2. Create a build.c or whatever naming you like.
// build game engine with a complex setup and dependencies

#define TWO_AM_BUILD_IMPL
#include "2am-builder.h"

int main(void) {
    AM_INIT(); // --> initialize builder state

    // ======== BUILD GLFW (static library) ==========
    AM_SET_COMPILER("clang", "c99");
    AM_SET_TARGET_DIRS("build", "build/vendor/glfw");
    AM_SET_FLAGS("-fPIC, -D_GLFW_X11, -D_GLFW_GLX");
    AM_ADD_INCLUDE("engine/src/vendor/glfw/include");

    const char *glfw_linux_file[] = {
        "context.c", "init.c", "input.c", "monitor.c", "vulkan.c", "window.c",
        "egl_context.c", "osmesa_context.c",

        // Linux-specific files
        "x11_init.c", "x11_monitor.c", "x11_window.c", "xkb_unicode.c",
        "glx_context.c", "linux_joystick.c", "posix_time.c", "posix_thread.c",
        NULL};

    AM_SET_SOURCE_SPECIFIC("engine/src/vendor/glfw/src", glfw_linux_file);
    AM_SET_TARGET_NAME("glfw3");
    AM_BUILD(BUILD_STATIC, false);

    AM_RESET(); // --> reset builder state

    // ======== BUILD ENGINE (shared library) ==========
    AM_SET_COMPILER("clang", "c99");
    AM_SET_COMPILER_WARN("-g, -Wall, -Wextra");
    AM_SET_FLAGS("-fPIC, -DENGINE_DEBUG);

    AM_SET_TARGET_DIRS("bin", "build/engine");
    AM_SET_TARGET_NAME("engine");
    AM_SET_SOURCE_WITH_EXCLUDE("engine/src", "vendor/glfw");

    AM_USE_PREBUILT_LIB("glfw3", "build"); // --> if using GLFW compile from source
    AM_USE_LIB("GL, m, dl, rt, X11");

    AM_BUILD(BUILD_SHARED, true);
    AM_GEN_DATABASE(); // --> generate compilation database (.json)

    AM_RESET(); // --> reset builder state

    // ======== BUILD APPLICATION ==========
    AM_SET_COMPILER("clang", "c99");
    AM_SET_COMPILER_WARN("-g, -Wall, -Wextra");

    AM_SET_TARGET_DIRS("bin", "build/myapp");
    AM_SET_TARGET_NAME("myapp");

    AM_ADD_INCLUDE("engine/src");
    AM_SET_SOURCE_ALL("myapp/src");

    AM_USE_PREBUILT_LIB("engine", "bin");
    AM_ADD_LINKER_FLAGS("-Wl, -rpath, .");
    AM_BUILD(BUILD_EXE, true);

    AM_RESET(); // --> reset builder state

    return 0;
}

About

2am Build system - A single-header C build. No dependencies.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Languages