1
0
Fork
You've already forked bbuild
0
No description
  • Shell 92.6%
  • Makefile 7.4%
Baptiste Daroussin bae2494e4a Add install.sh for bootstrapping new projects
Usage: git clone bbuild; cd myproject; ../bbuild/install.sh
2026年05月31日 10:46:43 +02:00
examples Update example configure.def with universal patterns 2026年05月31日 10:22:25 +02:00
mk Add PACKAGE_NAME, VERSION and datadir to mk/defs.mk.in 2026年05月31日 10:21:33 +02:00
tests Add tests for PACKAGE_NAME, VERSION and datadir in defs.mk 2026年05月31日 10:23:24 +02:00
configure Fix pkgconfigdir default bug 2026年05月31日 10:20:18 +02:00
install.sh Add install.sh for bootstrapping new projects 2026年05月31日 10:46:43 +02:00
LICENSE initial commit 2026年04月23日 09:04:58 +02:00
README.md Document PACKAGE_NAME, VERSION and datadir in README 2026年05月31日 10:34:41 +02:00

bbuild

A lightweight, portable build configuration system for C projects. Pure POSIX shell -- no external dependencies beyond a C compiler and standard Unix utilities:

  • mktemp
  • rm
  • sed
  • awk
  • mv
  • mkdir
  • dirname
  • tr
  • uname

bbuild inspired by autosetup with a single configure script and a set of reusable Makefile fragments (mk/). Build configuration is declared in an configure.def file using simple shell function calls.

Quick start

Copy into your project:

your-project/
 configure <- from bbuild
 config.guess <- optional, from GNU (for accurate host detection)
 configure.def <- you write this
 mk/
 common.mk <- from bbuild
 defs.mk.in <- from bbuild (customize if needed)
 prog.mk <- from bbuild (if building executables)
 static-lib.mk <- from bbuild (if building static libraries)
 lib.mk <- from bbuild (if building shared + static libraries)
 dir.mk <- from bbuild (if using recursive make)
 Makefile.in <- you write this
 src/
 ...

Then users run the familiar:

./configure --prefix=/usr/local
make
make install

Writing configure.def

configure.def is a POSIX shell script sourced by configure. It uses declarative-style function calls to describe the project's requirements.

Minimal example

use cc
define VERSION 1.0.0
options \
 "with-debug => enable debug build"
_configure_apply
cc_check_functions strlcpy
make_config_header config.h -auto VERSION
make_template mk/defs.mk.in
make_template Makefile.in

Skeleton with common patterns

use cc cc-lib pkg-config
define VERSION 0.1.0
options \
 "with-asan => build with AddressSanitizer" \
 "with-ubsan => build with UndefinedBehaviorSanitizer" \
 "enable-tests=1 => build and run tests (default: enabled)"
_configure_apply
cc_check_tools ar ranlib strip
# Required library via pkg-config
if ! pkg_config_init; then
 user_error "pkg-config is required"
fi
if ! pkg_config sqlite3; then
 user_error "sqlite3 is required"
fi
# Optional library
if pkg_config libfoo; then
 define HAS_FOO 1
fi
# Check functions
cc_check_functions strlcpy arc4random getprogname
# Check with specific link flags
cc_with "-libs -lm" cc_check_functions ceil
# Sanitizers
if opt_bool with-asan; then
 define_append ASAN_CFLAGS -O0 -g -fsanitize=address
 define_append ASAN_LDFLAGS -fsanitize=address
 define asan 1
fi
make_config_header config.h -auto VERSION
make_template mk/defs.mk.in
make_template Makefile.in

API Reference

Variables

Function Description
define KEY VALUE Set a variable
define_append KEY VALUE Append to existing variable (space-separated)
undefine KEY Remove a variable
get_define KEY Print the value of a variable (for use in $(...))
is_defined KEY Return true if the variable exists
is_true KEY Return true if defined and not "" or "0"
define_feature NAME [0|1] Define HAVE_NAME (uppercased, - becomes _)

Options

Function Description
options SPEC... Declare project options
opt_bool NAME Return true if boolean option is enabled
opt_str NAME Print value of string option; return true if set
_configure_apply Must be called after options() to process --flags

Option spec format: "name[=default\|:default] => description"

  • with-* options generate --with-NAME / --without-NAME flags
  • enable-* options generate --enable-NAME / --disable-NAME flags
  • name:default defines a string option with a default value

Compiler checks

Function Description
cc_check_functions FUNC... Check for C functions. Defines HAVE_FUNC
have_func FUNC Return true if function was found
cc_check_includes HDR... Check for headers. Defines HAVE_HDR
cc_check_members MEMBER... Check struct members (e.g. "struct stat.st_mtim")
cc_check_decls DECL... Check symbol declarations. Defines HAVE_DECL_X
cc_check_types TYPE... Check for types. Defines HAVE_TYPE
cc_check_tools TOOL... Check for tools (ar, ranlib, etc.)
cc_check_progs PROG... Check for programs. Returns 0 if found
cc_path_progs PROG... Like above, but defines PROG=/path/to/prog
cctest CODE Compile+link arbitrary C code. Returns 0 on success
cc_with SPEC COMMAND ARGS... Run command with temporary flags

cc_with spec format: -libs -lfoo -includes header.h -cflags -DFOO

pkg-config

Function Description
pkg_config_init Check for pkg-config/pkgconf. Call once before pkg_config
pkg_config SPEC Query a package. Defines PKG_NAME_{CFLAGS,LDFLAGS,LIBS}

pkg_config accepts version constraints: pkg_config "libfoo >= 2.0"

Output

Function Description
msg TEXT Print a message
msg_checking TEXT Print without newline (for check start)
msg_result TEXT Print with newline (for check result)
user_error TEXT Print error and exit
user_notice TEXT Print a notice

Generation

Function Description
make_config_header FILE [-auto PAT...] [-bare PAT...] Generate C #define header
make_template INPUT [OUTPUT] Process template with @VAR@ substitution

make_config_header behavior:

  • HAVE_* defines are always emitted
  • -auto PAT: emit matching keys (0 = #undef, integers bare, strings quoted)
  • -bare PAT: emit matching keys with values unquoted (useful for enum-like defines)

If OUTPUT is omitted, make_template strips .in or .bb suffix.

Standard variables

These are predefined by configure:

Variable Value
CC C compiler (auto-detected or from CC=...)
host Host triplet (e.g. x86_64-unknown-freebsd14.0)
prefix Installation prefix (default /usr/local)
bindir, sbindir, mandir, datadir, sysconfdir Derived from prefix
PACKAGE_NAME Project name (defined in configure.def via define PACKAGE_NAME)
VERSION Project version (defined in configure.def via define VERSION)
AR, RANLIB Archiver and ranlib tools (set by cc_check_tools)
abs_top_srcdir Absolute path to source directory
abs_top_builddir Absolute path to build directory
SHOBJ_CFLAGS Flags for position-independent code (-fPIC)
SH_LDFLAGS Shared library linker flags (-shared)
SH_SOEXT Shared library extension (.so or .dylib)
SH_SOPREFIX Soname flag prefix
SH_SOEXTVER Versioned extension format (.so.%s)

Host detection and config.guess

configure automatically detects the host triplet (e.g. x86_64-unknown-freebsd14.0, aarch64-unknown-linux6.1). It first looks for a [config.guess](https://savannah.gnu.org/projects/config) script in the project root; if not found, it falls back to constructing a triplet from uname.

If your project needs accurate host identification (e.g. to distinguish FreeBSD from Linux for platform-specific code), you can ship a copy of GNU config.guess in your project root. This is particularly useful for cross-compilation scenarios.

The host triplet is available in configure.def via get_define host and is commonly used with case for platform-specific logic:

_host=$(get_define host)
case "$_host" in
 *-freebsd*)
 define_feature capsicum
 ;;
 *-linux*)
 cc_with "-libs -lbsd" cc_check_functions getprogname
 ;;
 *-darwin*)
 define MACOS 1
 ;;
esac

Template syntax

Template files (.in) support two features:

Variable substitution

@VAR@ is replaced with the value of VAR from the define store.

CC= @CC@
PREFIX= @prefix@

Conditional blocks

@if asan
CFLAGS+= @ASAN_CFLAGS@
@endif
@if FEATURE
enabled=yes
@else
enabled=no
@endif

A variable is considered true if it is defined and not "" or "0". Conditionals can be nested.

Makefile fragments (mk/)

mk/defs.mk.in

Template for build variables. Processed by make_template mk/defs.mk.in to produce mk/defs.mk. Every other Makefile includes it:

include @builddir@/mk/defs.mk

The template includes PACKAGE_NAME, VERSION, CC, AR, RANLIB, SHOBJ_CFLAGS, SH_LDFLAGS, LIBSOEXT, SH_SOEXT, SH_PREFIX, PREFIX, top_srcdir, top_builddir, etcdir, libdir, bindir, sbindir, includedir, mandir, datadir, sysconfdir, and pkgconfigdir.

Projects with additional variables (e.g. textlibdir) can extend or customize this template in their own copy. The standard template also provides conditional @if blocks for asan, lsan, ubsan, tsan, and coverage, and includes all:, clean:, install:, check:, and distclean: targets.

mk/common.mk

Shared compilation rules. Provides .c.o and .c.pico (PIC) suffix rules with automatic dependency tracking.

mk/prog.mk

Build a single executable. Set PROG and SRCS:

include @builddir@/mk/defs.mk
PROG= myapp
SRCS= main.c utils.c
LOCAL_CFLAGS= -I$(top_srcdir)/include
LDFLAGS+= -lm
include $(MK)/prog.mk

mk/static-lib.mk

Build static libraries (lib$(LIB).a and lib$(LIB)_pic.a):

include @builddir@/mk/defs.mk
LIB= mylib
SRCS= foo.c bar.c
include $(MK)/static-lib.mk

mk/lib.mk

Build shared + static libraries:

include @builddir@/mk/defs.mk
LIB= mylib
SRCS= foo.c bar.c
include $(MK)/lib.mk

Produces lib$(LIB)$(LIBSOEXT), lib$(LIB)$(SH_SOEXT) (symlink), and lib$(LIB).a.

mk/dir.mk

Recursive make into subdirectories:

include @builddir@/mk/defs.mk
DIRS= src lib tests
include $(MK)/dir.mk

Running the tests

sh tests/run_tests.sh

License

ISC