Cut promotional copy

This commit is contained in:
Korze Warrior 2026-08-09 20:04:37 -07:00
commit 067eb271e4
8 changed files with 77 additions and 106 deletions

View file

@ -1,7 +1,6 @@
# IncludeBuild
A build system in one C header. Build scripts are C; there is no generator,
package, or build language to install.
Put `build.h` next to `build.c`.
```c
#define BUILD_IMPLEMENTATION
@ -15,22 +14,20 @@ int main(int argc, char** argv) {
```
```sh
cc -o build build.c # bootstrap once
./build # parallel incremental debug build
./build release # optimized build
./build run # build and run the first executable
cc -o build build.c
./build
./build release
./build run
./build clean
./build compdb # write compile_commands.json
./build compdb
./build help
```
`./build` recompiles itself when `build.c` or `build.h` changes. Source and
header timestamps, compiler depfiles, and the exact command line determine
what rebuilds. Use `./build -v` to see every decision.
`./build` recompiles itself when `build.c` or `build.h` changes. It also checks
compiler depfiles and the command used for each object. `./build -v` prints the
commands and rebuild reasons.
## API
Target constructors take a name and an initial source path or glob:
## Targets
```c
Target* executable(const char* name, const char* pattern);
@ -48,7 +45,7 @@ void use(Target* target, Target* library);
patterns are sorted and deduplicated. A pattern that matches nothing is an
error.
Configuration is one global struct:
## Configuration
```c
Target* app = executable("app", "src/**.c");
@ -63,16 +60,15 @@ if (config.release) {
}
```
Libraries passed to `use` are linked transitively in dependency order. Their
include directories propagate to users, and static libraries used by shared
libraries receive `-fPIC` automatically where required.
`use(app, library)` adds the library, its dependencies, and its include
directories. Static libraries linked into shared libraries are compiled with
`-fPIC` on Linux and macOS.
## Requirements
C99 and a GCC-compatible driver: GCC, Clang, or MinGW on Linux, macOS, or
Windows. `$CC`, `$CXX`, and `$AR` are honored.
C99. GCC, Clang, and MinGW are supported on Linux, macOS, and Windows. Compiler
defaults can be changed with `$CC`, `$CXX`, and `$AR`.
See [includebuild.com](https://includebuild.com) for the same reference and a
direct `build.h` download. The complete development repository, including
tests and the site source, is on [Forgejo](https://korze.org/code/includebuild).
GitHub is the minimal distribution mirror. Released under [CC0 1.0](LICENSE).
[Website](https://includebuild.com) ·
[Development repository](https://korze.org/code/includebuild) ·
[CC0](LICENSE)

39
build.h
View file

@ -1,4 +1,4 @@
/* IncludeBuild: a build system in one C header.
/* IncludeBuild
#define BUILD_IMPLEMENTATION
#include "build.h"
@ -9,8 +9,10 @@
return build();
}
Bootstrap once with `cc -o build build.c`, then use `./build`.
GCC-compatible C/C++ toolchains, C99, Linux/macOS/Windows, CC0.
cc -o build build.c
./build
C99; GCC, Clang, or MinGW; Linux, macOS, or Windows; CC0.
https://includebuild.com
*/
@ -30,9 +32,8 @@ extern "C" {
typedef struct Target Target;
/* Global configuration, read by build(). Assign fields after build_init and
before build. String fields must outlive build (literals are
perfect). Command-line flags override the corresponding fields. */
/* Set after build_init and before build. String values must remain valid until
build returns. Command-line options override the corresponding fields. */
typedef struct BuildConfig {
const char* root; /* project root; default "." */
const char* output_dir; /* artifact directory; default: root */
@ -54,33 +55,31 @@ typedef struct BuildConfig {
extern BuildConfig config;
/* Capture argv and parse the command line. Must be the first call. */
/* Parse argv. Call before declaring targets. */
#define build_init(argc, argv) build_init_from((argc), (argv), __FILE__)
void build_init_from(int argc, char** argv, const char* script_source);
/* Declare targets. Names must be portable file names. */
/* Names must be portable file names. */
Target* executable(const char* name, const char* pattern);
Target* static_library(const char* name, const char* pattern);
Target* shared_library(const char* name, const char* pattern);
/* Add sources by path or glob: `*` and `?` match within a path segment,
and `**` matches across directories, so "**.c" means every C file in the
tree (a leading directory, as in "src" + "**.c", narrows it). Patterns
that match nothing are an error. May be called repeatedly. */
/* Add a path or glob. `*` and `?` stop at directory boundaries; `**` does not.
"**.c" matches every C file. Prefix the pattern with a directory to limit
the search. Unmatched patterns are errors. */
void sources(Target* target, const char* pattern);
/* Add an include directory (-I). Propagates to targets that use this. */
/* Add an include directory. Users inherit it. */
void include_dir(Target* target, const char* dir);
/* Append target-specific compile / link flags. */
/* Append target-specific flags. */
void compile_flags(Target* target, const char* flags);
void link_flags(Target* target, const char* flags);
/* Link a library target into another target and inherit its include dirs. */
/* Add a library dependency. */
void use(Target* target, Target* library);
/* Execute whatever the command line asked for. Returns the process exit
code — `return build();` from main. */
/* Run the selected command and return its exit status. */
int build(void);
#ifdef __cplusplus
@ -241,7 +240,7 @@ static void incb_color_on(void) {
}
/* ----------------------------------------------------------------- memory */
/* Everything lives in one arena released at exit; nothing else to manage. */
/* Arena freed at exit. */
typedef struct incb_blk { struct incb_blk* next; size_t used, cap; } incb_blk;
static incb_blk* incb_mem;
@ -1199,7 +1198,7 @@ static const char* incb_usage =
"usage: ./build [debug|release] [verb] [options]\n"
"\n"
"verbs:\n"
" build compile and link everything (default)\n"
" build compile and link all targets (default)\n"
" run [target] build one executable, then run it (its args after --)\n"
" clean remove build outputs and state\n"
" compdb write compile_commands.json (auto-refreshed after)\n"
@ -2006,7 +2005,7 @@ static int incb_verb_build(void) {
(unsigned)linked, linked == 1 ? "" : "s",
incb_now() - t0, incb_g.jobs, INCB_COFF);
} else {
incb_say("%severything up to date%s", INCB_CGRN, INCB_COFF);
incb_say("%sall targets up to date%s", INCB_CGRN, INCB_COFF);
}
return 0;
}

View file

@ -1,10 +1,8 @@
# Examples
Every example follows the same two steps:
```bash
cc -o build build.c # bootstrap once
./build # from here on, ./build does everything
cc -o build build.c
./build
```
Try `./build run`, `./build release`, `./build -v`, `./build compdb`,
@ -12,6 +10,6 @@ Try `./build run`, `./build release`, `./build -v`, `./build compdb`,
| Example | Shows |
| --- | --- |
| [basic](basic/) | The smallest possible build script |
| [basic](basic/) | One source and one executable |
| [config](config/) | Global and target flags for debug/release |
| [library](library/) | A static library used by an executable |

View file

@ -1,14 +1,10 @@
# Basic Example
The smallest possible IncludeBuild project: one source file, one executable,
a six-line build script.
One source file and one executable.
```bash
cc -o build build.c # once
./build # build it
./build run # build it and run it
./build clean # remove outputs and .build/
cc -o build build.c
./build
./build run
./build clean
```
After the first compile you never touch `cc` again — if you edit `build.c`,
`./build` recompiles itself before doing anything else.

View file

@ -1,10 +1,9 @@
# Configuration
Debug and release are built in: `./build` uses `config.debug_flags`,
`./build release` uses `config.release_flags`, and each mode keeps its own
object tree so switching back and forth never rebuilds the world.
`./build` uses `config.debug_flags`. `./build release` uses
`config.release_flags`. Debug and release objects are stored separately.
The build script is ordinary C, so per-mode logic is an `if` on `config.release`:
Use `config.release` for mode-specific settings:
```c
if (config.release) {

View file

@ -1,4 +1,4 @@
/* IncludeBuild: a build system in one C header.
/* IncludeBuild
#define BUILD_IMPLEMENTATION
#include "build.h"
@ -9,8 +9,10 @@
return build();
}
Bootstrap once with `cc -o build build.c`, then use `./build`.
GCC-compatible C/C++ toolchains, C99, Linux/macOS/Windows, CC0.
cc -o build build.c
./build
C99; GCC, Clang, or MinGW; Linux, macOS, or Windows; CC0.
https://includebuild.com
*/
@ -30,9 +32,8 @@ extern "C" {
typedef struct Target Target;
/* Global configuration, read by build(). Assign fields after build_init and
before build. String fields must outlive build (literals are
perfect). Command-line flags override the corresponding fields. */
/* Set after build_init and before build. String values must remain valid until
build returns. Command-line options override the corresponding fields. */
typedef struct BuildConfig {
const char* root; /* project root; default "." */
const char* output_dir; /* artifact directory; default: root */
@ -54,33 +55,31 @@ typedef struct BuildConfig {
extern BuildConfig config;
/* Capture argv and parse the command line. Must be the first call. */
/* Parse argv. Call before declaring targets. */
#define build_init(argc, argv) build_init_from((argc), (argv), __FILE__)
void build_init_from(int argc, char** argv, const char* script_source);
/* Declare targets. Names must be portable file names. */
/* Names must be portable file names. */
Target* executable(const char* name, const char* pattern);
Target* static_library(const char* name, const char* pattern);
Target* shared_library(const char* name, const char* pattern);
/* Add sources by path or glob: `*` and `?` match within a path segment,
and `**` matches across directories, so "**.c" means every C file in the
tree (a leading directory, as in "src" + "**.c", narrows it). Patterns
that match nothing are an error. May be called repeatedly. */
/* Add a path or glob. `*` and `?` stop at directory boundaries; `**` does not.
"**.c" matches every C file. Prefix the pattern with a directory to limit
the search. Unmatched patterns are errors. */
void sources(Target* target, const char* pattern);
/* Add an include directory (-I). Propagates to targets that use this. */
/* Add an include directory. Users inherit it. */
void include_dir(Target* target, const char* dir);
/* Append target-specific compile / link flags. */
/* Append target-specific flags. */
void compile_flags(Target* target, const char* flags);
void link_flags(Target* target, const char* flags);
/* Link a library target into another target and inherit its include dirs. */
/* Add a library dependency. */
void use(Target* target, Target* library);
/* Execute whatever the command line asked for. Returns the process exit
code — `return build();` from main. */
/* Run the selected command and return its exit status. */
int build(void);
#ifdef __cplusplus
@ -241,7 +240,7 @@ static void incb_color_on(void) {
}
/* ----------------------------------------------------------------- memory */
/* Everything lives in one arena released at exit; nothing else to manage. */
/* Arena freed at exit. */
typedef struct incb_blk { struct incb_blk* next; size_t used, cap; } incb_blk;
static incb_blk* incb_mem;
@ -1199,7 +1198,7 @@ static const char* incb_usage =
"usage: ./build [debug|release] [verb] [options]\n"
"\n"
"verbs:\n"
" build compile and link everything (default)\n"
" build compile and link all targets (default)\n"
" run [target] build one executable, then run it (its args after --)\n"
" clean remove build outputs and state\n"
" compdb write compile_commands.json (auto-refreshed after)\n"
@ -2006,7 +2005,7 @@ static int incb_verb_build(void) {
(unsigned)linked, linked == 1 ? "" : "s",
incb_now() - t0, incb_g.jobs, INCB_COFF);
} else {
incb_say("%severything up to date%s", INCB_CGRN, INCB_COFF);
incb_say("%sall targets up to date%s", INCB_CGRN, INCB_COFF);
}
return 0;
}

View file

@ -3,7 +3,7 @@
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="IncludeBuild is a build system for C and C++ contained in one C header.">
<meta name="description" content="IncludeBuild build.h reference and download.">
<link rel="canonical" href="https://includebuild.com/">
<link rel="icon" href="images/favicon.svg?rev=20260809" type="image/svg+xml">
<link rel="stylesheet" href="css/minimal.css?rev=20260809">
@ -25,10 +25,8 @@
<main id="main">
<section>
<h2>IncludeBuild</h2>
<p>A build system for C and C++ contained in one C header.</p>
<p>Build definitions are C programs. Include <code>build.h</code>, declare the targets,
compile <code>build.c</code>, and run the resulting executable.</p>
<h2>build.h</h2>
<p>Declare C and C++ targets in <code>build.c</code>.</p>
<div class="download-options">
<a class="btn btn-primary" href="build.h" download>Download build.h</a>
<a class="btn btn-primary" href="https://korze.org/code/includebuild">Forgejo</a>
@ -59,22 +57,8 @@ int main(int argc, char** argv) {
./build clean</code></pre>
</div>
</div>
<p>Compile <code>build.c</code> once. Subsequent runs rebuild and restart the build
executable when <code>build.c</code> or <code>build.h</code> changes.</p>
</section>
<section>
<h2>Build behavior</h2>
<ul>
<li>Compiler depfiles track included headers.</li>
<li>Stored command lines detect changes to compilers, flags, modes, includes, and link inputs.</li>
<li>Independent compile and link operations run in parallel.</li>
<li>Targets can be executables, static libraries, or shared libraries.</li>
<li>Library dependencies propagate include directories and determine link order.</li>
<li>Source arguments accept paths and globs. <code>*</code> and <code>?</code> match within a directory; <code>**</code> crosses directories.</li>
<li>Incremental state is stored in <code>.build/</code> and can be deleted at any time.</li>
</ul>
<p><code>./build -v</code> prints commands and rebuild reasons.</p>
<p><code>./build</code> recompiles itself when <code>build.c</code> or
<code>build.h</code> changes. <code>./build -v</code> prints commands and rebuild reasons.</p>
</section>
<section id="api">
@ -94,6 +78,7 @@ void use(Target* target, Target* library);
int build(void);</code></pre>
<p>Constructors take a target name and an initial source path or glob. Use
<code>sources</code> to add more. A pattern that matches no files is an error.</p>
<p><code>use</code> adds a library, its dependencies, and its include directories.</p>
<h3>Configuration</h3>
<p>Set configuration after <code>build_init</code> and before <code>build</code>.
@ -122,8 +107,8 @@ config.jobs = 8;</code></pre>
<section>
<h2>Requirements</h2>
<p>C99 and a GCC-compatible compiler driver: GCC, Clang, or MinGW. The tool reads
<code>CC</code>, <code>CXX</code>, and <code>AR</code>.</p>
<p>C99. GCC, Clang, or MinGW on Linux, macOS, or Windows. Compiler defaults can be
changed with <code>CC</code>, <code>CXX</code>, and <code>AR</code>.</p>
<pre><code>curl -LO https://includebuild.com/build.h</code></pre>
</section>
</main>

View file

@ -3,7 +3,7 @@
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="Read or download the IncludeBuild source code.">
<meta name="description" content="IncludeBuild build.h source.">
<link rel="canonical" href="https://includebuild.com/source.html">
<link rel="icon" href="images/favicon.svg?rev=20260809" type="image/svg+xml">
<link rel="stylesheet" href="css/minimal.css?rev=20260809b">
@ -27,7 +27,6 @@
<main id="main">
<h2>build.h</h2>
<p>This is the header served by the download link.</p>
<div class="source-actions">
<a class="btn btn-primary" href="build.h" download>Download build.h</a>