0.3 - Learn how to use a build system

A build system is a software that reads a file that contains instructions of how the program need to be compiled, this is useful for control, automation and ease of other users to compile your software, also, there are some popular build systems:
Name | Description |
---|---|
Ninja | A small build system with a focus on speed |
Meson | Fast and user friendly build system, written in Python |
GNU Make | Simple and traditional build system |
For newbies, the “simpliest” make system may be GNU Make, there is a overview of the make systems displayed on the table:
Ninja
Ninja is a small build system with a focus on speed. It is designed to have its input files generated by other programs and is not typically written by hand. but is not hard to use only ninja.
Basic Concepts
- build.ninja: The main file containing build rules and dependencies.
- rule: Defines a command that Ninja can execute.
- build: Specifies how to generate an output file from input files using a rule.
Basic build.ninja File
# This is a comment
# build.ninja example for a simple C program
# Define a rule named 'cc' for compiling C files
rule cc
command = gcc -c $in -o $out
description = Compiling $in
# Define a rule named 'link' for linking object files
rule link
command = gcc $in -o $out
description = Linking $out
# Use the 'cc' rule to build main.o from main.c
build main.o: cc main.c
# Use the 'cc' rule to build hello.o from hello.c
build hello.o: cc hello.c
# Use the 'link' rule to build hello from main.o and hello.o
build hello: link main.o hello.o
# Define a default target
default hello
Building the Project
To build the project, run:
ninja
Ninja will read the build.ninja
file and execute the necessary commands to build the hello
target.
For more detailed information, refer to the official Ninja documentation.
GNU Make
GNU Make is a build automation tool that automatically builds executable programs and libraries from source code by reading files called Makefiles which specify how to derive the target program.
Basic Concepts
- Targets: What you want to build (e.g., executable files).
- Dependencies: Files that are used to create the targets.
- Commands: Shell commands used to build the targets from the dependencies.
Simple Makefile Example
# This is a comment
# Makefile for a simple C program
# Variables
CC = gcc #Compiler
CFLAGS = -Wall -g #Compiler flags/arguments
TARGET = myprogram #Final executable file
OBJS = main.o utils.o #Objects
# Default target
all: $(TARGET)
# Linking the target executable
$(TARGET): $(OBJS)
$(CC) $(CFLAGS) -o $(TARGET) $(OBJS)
# Compiling source files to object files
main.o: main.c
$(CC) $(CFLAGS) -c main.c
utils.o: utils.c
$(CC) $(CFLAGS) -c utils.c
# Clean up the build files
clean:
rm -f $(TARGET) $(OBJS)
Steps to Use GNU Make
- Create a Makefile:
- Create a file named
Makefile
in your project directory.
- Create a file named
- Define Variables:
- Variables like
CC
for the compiler,CFLAGS
for compiler flags,TARGET
for the output file, andOBJS
for object files can be defined to simplify the makefile and make it easier to maintain.
- Variables like
- Specify the Default Target:
- The first target in the Makefile is the default target, usually named
all
. This is what runs when you typemake
without any arguments.
- The first target in the Makefile is the default target, usually named
- Define Targets and Dependencies:
- Specify what files need to be built (targets) and what files are required to build them (dependencies).
- Write Commands:
- Commands to build the targets should be prefixed with a tab character.
- Add Clean Target:
- A
clean
target is useful to remove generated files, enabling a fresh build.
- A
Running Make
- Build the default target:
make
- Build a specific target:
make target_name
- Clean the build files:
make clean
This is a overview of the use of GNU Make, for more information, please refer to the GNU Make Manual.
Meson
Meson is a modern build system designed to be both fast and user-friendly. Unlike GNU Make, Meson typically uses Ninja as the backend to perform the actual build process, although it can also generate build files for other systems like Visual Studio and Xcode. Meson uses a high-level build description file (meson.build) to define the build process.
Basic concepts
- Project: Defines the overall project and its properties.
- Targets: These are the output artifacts like executables, libraries, or other files.
- Sources: The input source files that are compiled to create the targets.
- Dependencies: External libraries or tools required for building the project.
Simple project setup
- Create
meson.build
File:
project('myproject', 'c')
executable('myprogram', 'main.c', 'utils.c')
Building the Project
- Create a Build Directory and Run Meson:
meson setup builddir
- Compile the Project with Ninja:
meson compile -C builddir
- Run the Program:
./builddir/myprogram
Detailed Meson Build File
Here’s an extended example with more features:
project('myproject', 'c')
# Define build options
add_global_arguments('-Wall', language: 'c')
# Specify the executable target
executable('myprogram', ['main.c', 'utils.c'])
# Adding an optional library
libmath = dependency('m', required: false)
if libmath.found()
message('libm found')
executable('myprogram', 'main.c', dependencies: libmath)
else
message('libm not found')
endif
# Subdirectories (for larger projects)
subdir('src')
Adding a Subdirectory
Directory Structure:
myproject/
├── src/
│ ├── module.c
│ └── module.h
├── meson.build
├── main.c
├── utils.c
└── utils.h
Subdirectory meson.build
File (src/meson.build
):
sources = ['module.c']
library('mylib', sources)
Main meson.build
File:
project('myproject', 'c')
add_global_arguments('-Wall', language: 'c')
subdir('src')
executable('myprogram', ['main.c', 'utils.c'],
link_with: library('mylib', 'src/module.c')
)
Useful Commands
Configure with Options:
meson setup builddir --buildtype=release
Reconfigure the Build Directory:
meson configure builddir
Clean the Build Directory:
meson compile -C builddir --clean
For more details, please refer to the Meson Documentation
Summary
A build system is useful to agilize the process of compiling a program specially when multiple targets are expected, learning a build system is crucial on programmming if time eficiency is expected.