# Makefile Advanced **Recursive Make** handles multi-directory projects. Each subdirectory has its own Makefile; the top-level Makefile calls them. ```makefile # Top-level Makefile SUBDIRS = src lib test .PHONY: all clean $(SUBDIRS) all: $(SUBDIRS) $(SUBDIRS): $(MAKE) -C $@ clean: for dir in $(SUBDIRS); do \ $(MAKE) -C $$dir clean; \ done ``` `$(MAKE) -C $@` runs Make in the subdirectory. Each subdirectory builds independently. **Include files:** ```makefile include common.mk include config.mk ``` Include other Makefiles to share rules and variables. Useful for project-wide settings. **Defining and calling functions:** ```makefile define build_obj gcc $(CFLAGS) -c -o $(1) $(2) endef main.o: main.c $(call build_obj, main.o, main.c) ``` `define ... endef` defines a function. `$(call ...)` invokes it with arguments. Powerful for reusable recipes. **Variable scope:** Variables are global. Use functions for local scope: ```makefile define compile_files CC = gcc $(COMPILE_OBJS) endef ``` Variables inside functions are still global (no true local scope in Make). **Order-only prerequisites:** Some files should be prerequisites for creation, not modification: ```makefile build/%.o: src/%.c | build gcc -c $< -o $@ build: mkdir -p build ``` The `|` separates normal prerequisites from order-only. Changes to `build/` don't trigger rebuilds of `.o` files—only its existence matters. **Secondary expansion:** ```makefile .SECONDEXPANSION: app: $$^ gcc -o app $^ ``` `.SECONDEXPANSION` allows two-pass variable expansion. Rare; use for advanced metaprogramming. **Reading from files:** ```makefile VERSION = $(file < VERSION.txt) app: main.o gcc -o app main.o -DVERSION=\"$(VERSION)\" ``` `$(file < filename)` reads the file's contents. **Writing to files:** ```makefile $(file > build.log, Building...) $(file >> build.log, Done) ``` `$(file > ...)` writes, `$(file >> ...)` appends. **Debugging Makefiles:** Use `@echo` to print variables: ```makefile debug: @echo "SRCS: $(SRCS)" @echo "OBJS: $(OBJS)" @echo "CFLAGS: $(CFLAGS)" ``` See [[makefile-debugging]] for more techniques.