{"id":24369921,"url":"https://github.com/dangmoody/builder","last_synced_at":"2026-05-01T02:02:01.008Z","repository":{"id":271463300,"uuid":"842183516","full_name":"dangmoody/Builder","owner":"dangmoody","description":"A simple and powerful C++ build tool","archived":false,"fork":false,"pushed_at":"2025-03-16T15:28:59.000Z","size":4382,"stargazers_count":3,"open_issues_count":6,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-24T15:04:45.857Z","etag":null,"topics":["build","build-system","build-tool","cpp"],"latest_commit_sha":null,"homepage":"","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dangmoody.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-08-13T20:58:53.000Z","updated_at":"2025-03-16T15:29:02.000Z","dependencies_parsed_at":null,"dependency_job_id":"dfea843a-a677-44fc-91df-dcb94db2ff11","html_url":"https://github.com/dangmoody/Builder","commit_stats":null,"previous_names":["dangmoody/builder"],"tags_count":11,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dangmoody%2FBuilder","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dangmoody%2FBuilder/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dangmoody%2FBuilder/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dangmoody%2FBuilder/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dangmoody","download_url":"https://codeload.github.com/dangmoody/Builder/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248261972,"owners_count":21074229,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["build","build-system","build-tool","cpp"],"created_at":"2025-01-19T04:11:03.464Z","updated_at":"2026-05-01T02:02:01.001Z","avatar_url":"https://github.com/dangmoody.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Builder\n\nby Dan Moody.\n\nConfigure C/C++ builds by writing C++ instead of learning a separate build language.\n\n**BUILDER IS NOT A COMPILER.** - it turns your build config into compiler arguments and calls the compiler.\n\nOn windows it supports Clang, MSVC, and GCC.\n\nOn Linux it supports Clang and GCC.\n\n## Installation\n\n1. Download the latest release.\n2. Extract the archive somewhere.\n3. **Optional:** Add Builder to your `PATH`.\n\n## Quick Start\n\nWhen pointed at a **single** C/C++ source file, Builder will compile it:\n\n```\nbuilder main.cpp\n```\n\nBy default, Builder uses its bundled Clang, outputs the binary in the same folder, and names it after the source file. No config required.\n\n### Configuring your build\n\nFor multiple source files, and extra options, add `SetBuilderOptions` to your source file.\n\n```cpp\n#include \u003cbuilder.h\u003e // Builder will automatically resolve this include for you.\n\nBUILDER_CALLBACK void SetBuilderOptions( BuilderOptions *options, CommandLineArgs *args ) {\n\tBuildConfig config = {\n\t\t.binaryName   = \"my-program\",\n\t\t.binaryFolder = \"bin\",\n\t\t.sourceFiles  = { \"src/**/*.cpp\" },\n\t\t.defines      = { \"MY_DEFINE=1\" },\n\t};\n\n\tAddBuildConfig( options, \u0026config );\n}\n\nint main() { ... }\n```\n\nAny problems pass `-v` or `--verbose` when calling builder.\n\n### Separating build code from program code\n\n`BUILDER_DOING_USER_CONFIG_BUILD` is defined when Builder is compiling your source file into a config DLL. Use it to keep build code out of your program, and/or put `SetBuilderOptions` in a dedicated build file entirely:\n\n```cpp\n#if BUILDER_DOING_USER_CONFIG_BUILD\n#include \u003cbuilder.h\u003e\nBUILDER_CALLBACK void SetBuilderOptions( BuilderOptions *options, CommandLineArgs *args ) { ... }\n#endif\n```\n\nAdding `SetBuilderOptions` to a dedicated build file is recommended as it better supports incremental building.\n\nSee [`include/builder.h`](include/builder.h) for the full API reference.\n\n## Custom Command Line Arguments\n\nAny unrecognised flags are forwarded to your build script via `CommandLineArgs`:\n\n```cpp\n/* build.cpp */\nBUILDER_CALLBACK void SetBuilderOptions( BuilderOptions *options, CommandLineArgs *args ) {\n\tbool release = HasCommandLineArg( args, \"--release\" );\n\n\toptions-\u003eforceRebuild = HasCommandLineArg( args, \"--clean\" );\n\n\t// --jobs=8  →  \"8\"\n\tconst char *jobs = GetCommandLineArgValue( args, \"--jobs\" );\n}\n```\n\n```\nbuilder build.cpp --release --jobs=8 --clean\n```\n\nRun `builder -h` for built-in flags.\n\n## Multiple Configs\n\n```cpp\n/* build.cpp */\nBUILDER_CALLBACK void SetBuilderOptions( BuilderOptions *options, CommandLineArgs *args ) {\n\tBuildConfig appConfig = {\n\t\t.name         = \"app\",\n\t\t.binaryName   = \"my-program\",\n\t\t.binaryFolder = \"bin\",\n\t\t.sourceFiles  = { \"src/**/*.cpp\" },\n\t};\n\n\tBuildConfig testsConfig = {\n\t\t.name         = \"tests\",\n\t\t.binaryName   = \"my-program-tests\",\n\t\t.binaryFolder = \"bin\",\n\t\t.sourceFiles  = { \"src/**/*.cpp\", \"tests/**/*.cpp\" },\n\t\t.defines      = { \"TESTS_ENABLED\" },\n\t};\n\n\tAddBuildConfig( options, \u0026appConfig );\n\tAddBuildConfig( options, \u0026testsConfig );\n}\n```\n\n```\nbuilder build.cpp --config=app\nbuilder build.cpp --config=tests\n```\n\nIf two `BuildConfig`s have the same name, Builder will fail to do the build.  All `BuildConfig`s MUST have unique names.\n\n## Building Libraries\n\nSet `binaryType` on a `BuildConfig`:\n\n```cpp\nBuildConfig myLib = {\n\t.name       = \"my-lib\",\n\t.binaryType = BINARY_TYPE_STATIC_LIBRARY,  // or BINARY_TYPE_DYNAMIC_LIBRARY\n\t// ...\n};\n```\n\nUse `dependsOn` to express build order. Dependencies are built first and registered automatically - only call `AddBuildConfig` on the top-level config:\n\n```cpp\nBuildConfig program = {\n\t.name      = \"program\",\n\t.dependsOn = { myLib },\n\t// ...\n};\n\nAddBuildConfig( options, \u0026program );  // also registers myLib\n```\n\n## Extra Build Steps\n\n`OnPreBuild` and `OnPostBuild` let you run custom build steps such as copying files and codegen. These are available at two scopes:\n*  Export level (`BUILDER_CALLBACK`): runs before/after the entire build and is exported like `SetBuilderOptions`.\n* `BuildConfig` level: only runs before/after that specific config builds.\n\n```cpp\n#include \u003cbuilder.h\u003e\n#include \u003cstdio.h\u003e\n#include \u003ctime.h\u003e\n\n// this happens before ANY build step\nBUILDER_CALLBACK void OnPreBuild() {}\n\n// this happens after EVERY build step\nBUILDER_CALLBACK void OnPostBuild() {}\n\nstatic void PreBuild() {\n\tFILE *buildInfoHeader = fopen( \"src/generated/build_info.h\", \"w\" );\n\tfprintf( buildInfoHeader, \"#pragma once\\n\" );\n\tfprintf( buildInfoHeader, \"#define BUILD_TIMESTAMP %lldLL\\n\", (long long) time( NULL ) );\n\tfclose( buildInfoHeader );\n}\n\nstatic void PostBuild() {\n#ifdef _WIN32\n\tsystem( \"copy bin\\\\engine.dll bin\\\\game\\\\\" );\n#else\n\tsystem( \"cp bin/engine.dll bin/game/\" );\n#endif\n}\n\nBUILDER_CALLBACK void SetBuilderOptions( BuilderOptions *options, CommandLineArgs *args ) {\n\tBuildConfig config = {\n\t\t.binaryName   = \"game\",\n\t\t.binaryFolder = \"bin/game\",\n\t\t.sourceFiles  = { \"src/**/*.cpp\" },\n\t\t.OnPreBuild   = PreBuild,\n\t\t.OnPostBuild  = PostBuild,\n\t};\n\n\tAddBuildConfig( options, \u0026config );\n}\n```\nIn this example, the flow would be `OnPreBuild` -\u003e `PreBuild` -\u003e Config Builds -\u003e `PostBuild` -\u003e `OnPostBuild`.\n\n## Choosing a Compiler\n\nBy default Builder uses its bundled Clang install. Override it in your build script:\n\n```cpp\noptions-\u003ecompilerPath    = \"C:/path/to/gcc\";\noptions-\u003ecompilerVersion = \"15.1.0\";  // optional - warns on mismatch\n```\n\n### MSVC\n\nSet `compilerPath` to `\"cl\"` and Builder will locate the MSVC toolchain and Windows SDK automatically. A hard-coded path works too but requires you to manage SDK paths yourself.\n\n### Windows Runtime\n\nOn Windows, the C and C++ runtimes come in both static and dynamic (DLL) variants. By default Builder links against the static runtime. Set `linkAgainstWindowsDynamicRuntime` to link against the dynamic runtime instead:\n\n```cpp\noptions-\u003elinkAgainstWindowsDynamicRuntime = true;\n```\n\nThis adds the `_DLL` preprocessor definition, which changes linking behavior to use the dynamic runtime. It has no effect on Linux.\n\n## Visual Studio and Rider\n\n```cpp\nBUILDER_CALLBACK void SetBuilderOptions( BuilderOptions *options, CommandLineArgs *args ) {\n\tBuildConfig config = {\n\t\t.binaryName   = \"my-game\",\n\t\t.binaryFolder = \"bin\",\n\t\t.sourceFiles  = { \"src/**/*.cpp\" },\n\t\t// ...\n\t};\n\n\tAddBuildConfig( options, \u0026config );\n\n\t// pass --sln to generate; skips compilation\n\toptions-\u003egenerateSolution = HasCommandLineArg( args, \"--sln\" );\n\toptions-\u003esolution = {\n\t\t.name      = \"my-game\",\n\t\t.path      = \"visual_studio\",\n\t\t.platforms = { \"x64\" },\n\t\t.projects  = {\n\t\t\t{\n\t\t\t\t.name    = \"my-game\",\n\t\t\t\t.configs = {\n\t\t\t\t\t{ \"debug\",   config, {             }, {} },\n\t\t\t\t\t{ \"release\", config, { \"--release\" }, {} },\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t};\n}\n```\n\nGenerated projects call Builder - Visual Studio project property edits have no effect. Re-run Builder to update them. Generated solutions also open in JetBrains Rider.\n\n## VS Code\n\n```cpp\n// pass --vscode to generate; skips compilation\noptions-\u003egenerateVSCodeJSONFiles = HasCommandLineArg( args, \"--vscode\" );\noptions-\u003evsCodeJSONOptions = {\n\t.builderPath          = \"builder\",\n\t.cppPropertiesConfigs = {\n\t\t{ debugConfig, VSCODE_INTELLISENSE_MODE_LINUX_CLANG_X64 },\n\t},\n\t.taskConfigs          = {\n\t\t{ debugConfig                    },\n\t\t{ releaseConfig, { \"--release\" } },\n\t},\n\t.launchConfigs        = {\n\t\t{ .binaryName = \"bin/debug/my-program\",   .debuggerType = VSCODE_DEBUGGER_TYPE_CPPVSDBG   },\n\t\t{ .binaryName = \"bin/release/my-program\", .debuggerType = VSCODE_DEBUGGER_TYPE_CPPDBG_GDB },\n\t},\n};\n```\n\nGenerates `.vscode/c_cpp_properties.json`, `.vscode/tasks.json`, and `.vscode/launch.json`. `builderPath` defaults to `\"builder\"`, assuming it is on your `PATH`.\n\n## Zed\n\n```cpp\n// pass --zed to generate; skips compilation\noptions-\u003egenerateZedJSONFiles = HasCommandLineArg( args, \"--zed\" );\noptions-\u003ezedJSONOptions = {\n\t.builderPath  = \"builder\",\n\t.taskConfigs  = {\n\t\t{ debugConfig                    },\n\t\t{ releaseConfig, { \"--release\" } },\n\t},\n\t.debugConfigs = {\n\t\t{ .binaryName = \"bin/debug/my-program\"   },\n\t\t{ .binaryName = \"bin/release/my-program\" },\n\t},\n};\n```\n\nGenerates `.zed/tasks.json` and `.zed/debug.json`.\n\n## Compilation Database\n\n```cpp\noptions-\u003egenerateCompilationDatabase = true;\n```\n\nGenerates `compile_commands.json` on a successful build. Compatible with clangd, CLion, VS Code, and other tools that support the [JSON Compilation Database](https://clang.llvm.org/docs/JSONCompilationDatabase.html) format.\n\n\n## Motivation\n\nC++ has no standard build system, so at some point every C++ programmer has to pick one and every option asks the same thing of you: learn a new language.  CMake has its own DSL, Makefiles have their own syntax and rules, Premake uses Lua, Meson uses Python.  Even if you learn one well, the knowledge doesn't transfer to the next project that uses a different one and you have to learn a project's build system all over again.\n\nYou already know C++.  Why should configuring a C++ build require learning anything else?\n\nBuilder's answer is to not require it.  Your build config is just a C++ source file.  The types are C++ structs.  The logic is C++.  If you can write C++, you already know how to use Builder.\n\n## Contributing\n\nYes!\n\nPlease see [Contributing.md](doc/Contributing.md).\n\n\n## Credits\n\nBuilder would not have been possible without the following people who deserve, at the very least, a special thanks:\n\n* Dale Green\n* [Aiden Knight](https://github.com/aiden-knight) (Lots of fixes for lots of things)\n* [Ed Owen](https://github.com/eddyowen) (Compilation database support, QoL improvements)\n* Yann Richeux (Bug fixes)\n* Tom Whitcombe (Visual Studio project generation)\n* Mike Young (Linux port)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdangmoody%2Fbuilder","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdangmoody%2Fbuilder","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdangmoody%2Fbuilder/lists"}