In C/C++ development, code is split into dependencies (e.g., your app.c "borrows" a login function from auth_library.c). If the library isn't compiled into an object file first, your app cannot be built. The make utility automates this by following a script called a Makefile.
Key principles of makefile:
- Makefile: A file containing variables, targets, and commands to compile and link your project.
- Make Utility: A command-line tool that processes the Makefile instructions.
- Dependency Management: It specifies which files must be created before others.
- Efficiency: It only recompiles files that have changed since the last build.
Project Structure:
To demonstrate, we will use four files:
- client.c: Contains the main() function.
- server.c: Contains the greetings() function definition.
- server.h: Header file declaring the greetings() function.
- makefile.mk: The build script.
1. server.h (Header)
It declares the function so other files can use it.
void greetings();
2. server.c (Function Definition)
Implements the greeting logic here.
#include "server.h"
#include <stdio.h>
void greetings() {
printf("geeksforgeeks!");
}
3. client.c (Main Program)
The entry point that calls the external function.
#include <stdio.h>
#include "server.h"
int main() {
printf("hey there, welcome to ");
greetings();
return 0;
}
4. makefile.mk (Build Script)
This file defines the targets (what to build) and prerequisites (what is needed).
Important: Commands must be preceded by a Tab character, not spaces.
# Target: Prerequisites
# [Tab] Command
a: client.o server.o
gcc client.o server.o -o a
client.o: client.c server.h
gcc -c client.c
server.o: server.c server.h
gcc -c server.c
Execution Steps
1. Compile the Project: Run the make command with the -f flag to specify your filename.
make -f makefile.mk
This creates an executable named a (Windows) or a.out (Linux).
2. Run the Program:
For Windows run : a
or,
For Linux run : ./a
Output:
hey there, welcome to geeksforgeeks!
How it Works Internally
- Dependency Graph: Make builds a visual map of which files depend on others.
- Topological Sorting: It uses this algorithm to determine the exact sequence of compilation.
- Timestamps: It compares the "Last Modified" time of the source file vs. the object file, if the source is newer, it triggers a recompile.
When to Use Make
- Large Projects: When managing dozens or hundreds of source files.
- Automated Testing: To run a suite of tests immediately after a successful build.
- Cross-Platform Builds: To handle different compiler flags for different operating systems.
- Time Saving: To avoid recompiling the entire project when you only changed one line of code.