0.3 - Learn how to use a build system

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

  1. Create a Makefile:
    • Create a file named Makefile in your project directory.
  2. Define Variables:
    • Variables like CC for the compiler, CFLAGS for compiler flags, TARGET for the output file, and OBJS for object files can be defined to simplify the makefile and make it easier to maintain.
  3. Specify the Default Target:
    • The first target in the Makefile is the default target, usually named all. This is what runs when you type make without any arguments.
  4. Define Targets and Dependencies:
    • Specify what files need to be built (targets) and what files are required to build them (dependencies).
  5. Write Commands:
    • Commands to build the targets should be prefixed with a tab character.
  6. Add Clean Target:
    • A clean target is useful to remove generated files, enabling a fresh build.

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.



© 2025 Easy and fast Programming guide For C

Powered by Tessera for Jekyll