What is Makefile

Makefile consists of a set of RULES. Rules consists of 3 parts
  Target: target and pre-requisites are separated by a colon (:)
  List of pre-requisites/Dependencies.
  A command: The command must be preceded by a tab (NOT spaces)

target: pre-requisite-1 pre-requisite-2 ...
command                
            

Terms

PHONY/Artificial Targets

These are not real name of a file, it is just a name for a recipe to be executed. Example: clean, all, install.

Variables

A variable begins with a `$`
Types of Variables
1. Multicharacter variables are enclosed within parentheses (...) or braces {...}. Eg: (CC_FLAGS)
2. Singlecharacter variables do not need the parentheses. Eg: ^
3. Automatic Variables These are automatically(note automatically) set by make whenever rule is matched.
Automatic Variables
Variable Meaning
$@ Target name, name of the file being generated
$* Target filename without extension
$< 1st Pre-requisite/Depends filename
$^ Filename of all Pre-requisites seperated by spaces(discard Duplicates)
$+ similar to $^, but includes duplicates
$? names of all prerequisites that are newer than the target, separated by spaces
$% target member name. When target is foo.a(bar.o) ‘$%’ is bar.o
$(COMPILE.c) consists of compiler name and compiler options
$(COMPILE.cpp) consists of compiler name and compiler options
$(COMPILE.cpp) consists of compiler name and compiler options
$(OUTPUT_OPTION) could be -o $@
LINK.cc (CXXFLAGS) (LDFLAGS) $(TARGET_ARCH)
$(LINK.cpp) Equal to $(LINK.cc)
make --print-data-base ALL set of implicit pattern rules

Examples

Hello World

Code Makefile Explanation

// hello.c
#include <stdio.h>   
int main() {
    printf("Hello, world!\n");
    return 0;
}
                    

//Running make without target hits `all`
all: hello.exe

hello.exe: hello.o
        gcc -o hello.exe hello.o

hello.o: hello.c
        gcc -c hello.c
        
clean:
        rm hello.o hello.exe                        
                    
make
1. make command reaches Rule = all.
  Rule = all has pre-requisite hello.exe(does not exist), so it looks for a rule to create it.
2. Reaches Rule = hello.exe
  Pre-requisite hello.o(does not exist) so it looks for a rule to create it.
3. Reaches Rule = hello.o
  Pre-requisite hello.c(exists, stay here and execute)
  Runs the command gcc -c hello.c
  Rule finishes, goes back to Rule = hello.exe
4. Reaches Rule = hello.exe
  Pre-requisite hello.o(exists)
  Run its command gcc -o hello.exe hello.o
5. Finally, Rule = all does nothing.

make clean
Specifying the target to be build with make.

// hello.c
#include <stdio.h>   
int main() {
    printf("Hello, world!\n");
    return 0;
}                        
                    

all: hello.exe

hello.exe: hello.o
    gcc -o $@ $<
                                        
hello.o: hello.c
    gcc -c $<
        
clean:
    rm hello.o hello.exe
                    
1. Running make without target hits `all`

2. gcc -o $@ $< $< means 1st pre-requisite filename = hello.o
  $@ means target file name = hello.exe

3. gcc -o $@ $< = gcc -o hello.exe hello.o
  $< means 1st pre-requisite filename = hello.c

4. gcc -c $< = gcc -c hello.c

Example 2

Code Makefile Explanation

//init.cpp
#include "openssl/bio.h"
#include "openssl/ssl.h"
#include "openssl/err.h"
void initialize_openssl() {
    /* Initializing OpenSSL */
    SSL_load_error_strings();
    ERR_load_BIO_strings();
    OpenSSL_add_all_algorithms();
}

//init.h
void initialize_openssl();

//main.cpp
#include
void main(){
    initialize_openssl();
}
                    

# Declared Variables
IDIR=.
CC=gcc
# List of flags to pass to compilation command
CFLAGS=-I$(IDIR)
LDFLAGS=-L/usr/lib64
OBJ= init.o main.o

make: $(OBJ)
    $(CC) -o $@ $^ $(CFLAGS) $(LDFLAGS) -lssl -lcrypto