Rbuild is a lightweight, Makefile-based build system inspired by the Linux Kernel Kbuild.
Its goal is to make large, hierarchical C projects easy to manage by:
-
letting each directory describe only its own files,
-
building everything via recursive
makein a controlled and predictable way, -
and supporting single-target builds such as:
make src/module/ make src/module/foo.o
Each directory has its own Makefile, describing the objects and libraries it builds and which subdirectories it contains.
A typical Rbuild project follows this layout:
project/
├─── include/ # contains all the header files.
├─── lib/ # (optional) used for static and dynamic libraries.
├─── scripts/ # contains Rbuild Makefiles to build the project.
├─── src/ # contains the project source code.
└─── Makefile # top level MakefileIn the top level Makefile, set the following variables:
export TARGET := main
export SRC_DIR := src
export LIB_DIR := lib
export SHLIB_DIR := lib
export INCLUDE_DIR := includeTARGET is the name of the final executable.
LIB_DIR (optional) static libraries directory.
SHLIB_DIR (optional) shared libraries directory. It can be different from LIB_DIR.
Each directory that contains source code gets its own Makefile. Each Makefile is only responsile for building objects in its directory.
There are two user available variables to tell Rbuild which files to produce:
-
objs: all objects added here are combined in a singlebuilt-in.ofor that directory. -
libs: all objects added here are combined in a singlelib.afor that directory. The use of this variable should be restricted toLIB_DIR.
Subdirectories can be added to both variables to tell Rbuild to descend in them and look for a Makefile.
project/
├── include/
│ ├── amazing_lib.h
│ ├── file1.h
│ ├── libcool/file2.h
│ └── module/file3.h
├── src/
│ ├── Makefile
│ ├── main.c
│ ├── file1.c
│ └── module/
│ ├── Makefile
│ └── file3.c
└── lib/
├── Makefile
│ ├── amazing_lib.c
│ ├── helper.c
│ └── helper.h
└── libcool/
├── Makefile
└── file2.c
-
src/Makefile:objs += main.o file1.o module/ -
src/module/Makefile:objs += file3.o -
libs/Makefile:libs += amazing_lib.o helper.o libcool/ -
libs/libcool/Makefile:libs += file2.o
To create a shared library, use shlibs to specify the library name. Then, use <libname>-objs to specify the objects it needs. To link it, add the library to SHARED_LIBS in the project level Makefile.
-
Makefile:SHARED_LIBS := foo -
lib/Makefile:shlibs += libfoo.so libname-objs := bar.o baz.o
To add existing static or dynamic libraries not in $PATH, simply place them in LIB_DIR/SHLIB_DIR.
To link the libraries, add them to STATIC_LIBS/SHARED_LIBS in the project level Makefile.
ASFLAGS, CFLAGS, WARNINGS, LDFLAGS can be set directly in the project level Makefile. They are applied to the whole project.
Warnings must be specified without the -W prefix, it will be added automatically.
CFLAGS := -std=c99
WARNINGS := all extraasflags, ccflags, cppflags, ldflags are used to set additional flags to the assembler, compiler, preprocessor and linker, respectively. These flags are applied only to the current directory of the Makefile.
ccflags += -O2subdir-asflags, subdir-ccflags set additonal flags to the assembler and compiler, respectively. These flags are applied in the current directory of the Makefile and in every subdirectory.
asflags-<file> and ccflags-<file> can be used to set file specific flags for the assembler and the compiler, respectively. These flags are only applied to the corresponding source file. Example:
objs += file1.o file2.o
ccflags-file1 := -Wshadow -DDEBUG
asflags-file2 := -march=armv8-a