Learn through the super-clean Baeldung Pro experience:
>> Membership and Baeldung Pro.
No ads, dark-mode and 6 months free of IntelliJ Idea Ultimate to start with.
Last updated: January 21, 2026
In Linux, Makefiles are powerful tools for automating build processes, but their syntax can sometimes be tricky, especially when it comes to conditional statements. The syntax differs significantly from traditional programming languages, leading to confusion and errors. A common issue is attempting to use if-else statements directly within recipe lines, which doesn’t work as expected.
In this tutorial, we’ll explore the syntax and examples of using if-else blocks in Makefiles.
We use several kinds of conditional directives in a Makefile:
We’ll explore examples of the above conditionals in the subsequent sections.
Let’s take a look at the basic syntax for an if-else statement in a Makefile:
ifeq (condition)
# Commands if condition is true
else
# Commands if condition is false
endif
The above snippet is a basic skeleton on the conditional statements in a Makefile. We’ll explore the above directives using various examples.
The ifeq directive tests if two strings are equal:
MODE = debug
ifeq ($(MODE),debug)
CFLAGS = -g -O0 -DDEBUG
else
CFLAGS = -O2
endif
In this example, if MODE equals “debug”, then CFLAGS takes on debugging flags; otherwise, it takes on optimization flags.
The ifneq directive tests if two strings aren’t equal to each other:
OS = linux
ifneq ($(OS),windows)
RM = rm -f
else
RM = del
endif
Here, if OS isn’t “windows”, the RM command takes the Unix version; otherwise, it takes the Windows command.
The ifdef directive tests whether or not a variable is defined:
ifdef DEBUG
CFLAGS += -g -DDEBUG
endif
In this example, if DEBUG is defined (regardless of its value), the directive adds debugging flags to CFLAGS.
The ifndef directive tests if a variable isn’t defined:
ifndef CC
CC = gcc
endif
In this case, if the CC variable isn’t defined, the Makefile assigns “gcc” as its default value. We commonly use this pattern in Makefiles to provide default values that users can override.
In the following sections, we’ll explore examples that combine various aspects of the above conditionals into a Makefile.
Here’s an example that demonstrates the usage of conditional statements for handling different operating systems:
# Define the default target
all: hello
# Check the operating system
ifeq ($(OS),Windows_NT)
DETECTED_OS := Windows
else
DETECTED_OS := $(shell uname -s)
endif
# Target that uses the detected OS
hello:
@echo "Hello from $(DETECTED_OS)"
@echo "This is a Make example"
# Conditional target behavior
ifeq ($(DETECTED_OS),Windows)
install:
@echo "Installing on Windows..."
else ifeq ($(DETECTED_OS),Darwin)
install:
@echo "Installing on macOS..."
else
install:
@echo "Installing on Linux or other OS..."
endif
In the above example, we initialize the the variable DETECTED_OS based on environment variable OS. The details of the above steps are:
Subsequently, we use the variable DETECTED_OS for installing the appropriate software based on the operating system.
If we need conditional logic within a recipe, we use shell conditionals:
check_file:
@if [ -f "somefile.txt" ]; then \
echo "File exists"; \
else \
echo "File does not exist"; \
fi
Let’s break down the above code:
The entire command is actually a single shell command (a Bash if-statement). In a proper Makefile, this would typically be formatted with proper indentation for readability. In above example, we’re executing the command prefixed with @ in a Bash subshell.
We can also use if conditionals for inline functions:
# Using $(if) function
MESSAGE := $(if $(DEBUG),Debugging mode, Release mode)
# Using computed variable names
MODE := debug
COMPILER_$(MODE) := gcc -g
COMPILER_release := gcc -O2
compile:
@echo "Using compiler: $(COMPILER_$(MODE))"
The above example illustrates inline functions using $(if …) syntax:
We also use a computed variable based on the value of the MODE variable. This allows us to initialize the appropriate compiler parameters and use it for compiling the program.
We can combine the shell command in Makefile to check the required disk space:
# define the minimum disk space required
MIN_SPACE_MB=1000
valid-env:
@echo "validating build env ..."
ifeq ($(shell if [ $$(df -m . | tail -1 | awk '{print $$4}') -lt $(MIN_SPACE_MB) ];then echo 1; else echo 0; fi),1)
$(error Insufficient disk space. At least $(MIN_SPACE_MB)MB required)
endif
The above example illustrates a complex example of checking the environment for available disk space. The steps are:
One important idea of note is that in Makefiles, we can’t directly split a shell command across multiple lines. A separate shell instance typically executes every recipe. As a result, the variables defined in one line aren’t available in the next. This leads to variable scope limitations.
In this article, we learned various ways of using if-else blocks in a Makefile. Understanding conditional statements in Makefiles is essential for creating versatile and maintainable build systems. By properly implementing if-else logic in our Makefiles, we can ensure our build processes are robust and flexible across different platforms and configurations.