C-Makefiles

A make- is a build automation tool used to compile and build projects.
Very useful if you have multiple source files.
Makefile is just a configuration file that specifies how the project should be built(rules) and the dependencies between different files.
Makefile has rules and dependencies.
When it's useful?
When you have a large project- a large program with many source files
Dependency management- different files depend on each other
efficiency - recompiles only parts of code that changed hence saving time.
Why use it:
Automation- saves you from having to manually recompile files
Dependencies tracking- able to detect changes and build.
Consistency- ensures consistent build process in different environments for different developers.
How to use it:
Start by creating a file named makefile
Define rules -write rules that specify how to build target files(output files) from dependencies(input files)
Use variables - define variables for compiler options source files and other parameters
create phony targets - for actions that don't produce files but trigger certain tasks e.g cleaning or testing
dependencies- explicitly list dependencies(input files) for each target for proper rebuild
CC = gcc
CFLAGS = -Wall
all: my_program
my_program: main.o utils.o
$(CC) $(CFLAGS) -o my_program main.o utils.o
main.o: main.c
($CC) $(CFLAGS) -c my_program main.c
utils.o: utils.c
$(CC) $(CFLAGS) -c my_program utils.c
clean:
rm -f *.o my_program
Explicit rules
specify how to build a specific target explicitly.
target: prerequisite
recipe
They are useful when you want to specify or be specific on how to build a specific target.
They are explicitly done in makefile.
my_program: main.o utils.o
gcc -Wall -o my_program main.o utils.o
main.o: main.c utils.h
gcc -Wall -c main.c
utils.o: utils.c utils.h
gcc -Wall -c utils.c
Implicit rules
These are predefined rules that do not need explicit instructions.
Often written as pattern rules, specifying a pattern for target and prerequisite names.
%.o: %.c
recipe
They are handy when you have consistent patterns for building patterns from source files.
CC = gcc
CFLAGS = -Wall
my_program: main.o utils.o
$(CC) $(CFLAGS) -o my_program main.o utils.o
main.o utils.o: %.o: %.c
$(CC) $(CFLAGS) -c $<
common rules
Simple rule for compiling source files
%.o: %.c
$(CC) $(CFLAGS) -c $<
linking them to an executable
my_program: main.o utils.o
$(CC) $(CFLAGS) -o my_program main-o utils.o
Phony targets
.PHONY: clean
clean:
rm -f*.o my_program
Default rule
.DEFAULT_GOAL := all
all: my_program
Setting variables
Basic assignment
variable_name = value
Appending to variables
VARIABLE_NAME += new_value
Using variables
Referencing variables
$(VARIABLE_NAME)
Defining targets with variables
TARGET: $(VARIABLE_NAME):
recipe
Automatic variables
target: prerequisite1 prerequisite2
command $@ $^
Example
CC = gcc
CFLAGS = -Wall
SOURCES = main.c utils.c
OBJECTS = $(SOURCES:.c=.o)
EXECUTABLE = my_program
all: $(EXECUTABLE)
$(EXECUTABLE): $(OBJECTS)
$(CC) $(CFLAGS) -o $@ $^
%.o:%.c
$(CC) $(CFLAGS) -c $<
clean:
rm -f $(OBJECTS) $(EXECUTABLE)



