Conditional directives allow different behavior based on variables or environment. Common: ifeq, ifneq, ifdef, ifndef.
ifeq (equal):
ifeq ($(OS), Linux)
LDFLAGS = -lrt
else
LDFLAGS = -framework CoreFoundation
endif
If $(OS) equals Linux, set Linux-specific flags. Otherwise, use macOS flags.
ifneq (not equal):
ifneq ($(PLATFORM), windows)
CFLAGS = -fPIC
endif
If $(PLATFORM) is not windows, add position-independent code flag.
ifdef (defined):
ifdef DEBUG
CFLAGS += -g -O0
else
CFLAGS += -O3
endif
If DEBUG is defined (even if empty), use debug flags. Otherwise, optimize.
ifndef (not defined):
ifndef INSTALL_PREFIX
INSTALL_PREFIX = /usr/local
endif
If INSTALL_PREFIX is not set, use a default.
Detecting the platform:
UNAME_S := $(shell uname -s)
ifeq ($(UNAME_S), Linux)
LDLIBS = -lrt
endif
ifeq ($(UNAME_S), Darwin)
LDLIBS = -framework CoreFoundation
endif
Detect the OS at make time and set appropriate flags.
Conditional compilation:
ifdef ENABLE_TESTS
SRCS += test.c
TEST_TARGET = run_tests
else
TEST_TARGET =
endif
app: $(SRCS)
gcc -o app $(SRCS)
test: $(TEST_TARGET)
@echo "Tests skipped (use: make ENABLE_TESTS=1)"
$(TEST_TARGET): test.c
./run_tests
Enable tests with make ENABLE_TESTS=1 test.
Nested conditionals:
ifdef RELEASE
CFLAGS = -O3
ifdef STRIP
LDFLAGS += -s
endif
else
CFLAGS = -g -O0
endif
Conditionals can be nested. Use indentation for clarity.
Conditional includes:
ifdef CONFIG_FILE
include $(CONFIG_FILE)
else
include default_config.mk
endif
Include different configuration files based on conditions.
Example: Debug vs Release builds:
ifdef DEBUG
CFLAGS = -g -O0 -DDEBUG
TARGET = app_debug
else
CFLAGS = -O3
TARGET = app
endif
$(TARGET): main.o util.o
gcc -o $@ main.o util.o
clean:
rm -f *.o app app_debug
Build with make DEBUG=1 for debug, make for release.