Goal : To create a Make file to generate an executable using makefile in Ubuntu.
Requirements : Ubuntu, Knowledge of c programming.
First we will create a simple hello world c program.
Creating the source code for Hello World Program:
Contents of main.c
#include int main() { printf("Hello world!"); }
Compiling the source file using gcc
gcc main.c
This will generate a executable file as a.out.
1.b Generating a executable file with a given name
gcc main.c -o hello
1.c Modularising the print function
Modularising is good as they can be reused, archived as library, and for many more reasons
#include void print_hello(); void print_hello() { printf("Hello world!"); } int main() { print_hello(); }
1.d Creating seperate files for modules:
Its good to have releatives modules in a sepearate files
Content of main.c
int main() { print_hello(); }
Content of hello_func.c
#include void print_hello() { printf("Hello world!"); }
Compiling the files
gcc hello_func.c main.c -o hello.out
1.d Creating header files
Every c file will have some header files included.
Content of main.c
#include "hello.h" int main() { print_hello(); }
Content of hello_func.c
#include "hello.h" void print_hello() { printf("Hello world!"); }
Content of hello.h
#include void print_hello(void);
1.e Organizing the files
Its good to put up files in a organized manner.
So we put our modules, main and header files into source, test and include dirctory respectively as bellow.
And build directory to do the building.
.
├── build
├── include
│ └── hello.h
├── src
│ └── hello_func.c
└── test
└── hello.c
Compiling
cd build
gcc -I ../include/ ../src/hello_func.c ../test/hello.c -o hello.out
This will generate a hello.out in build directory
Now, we have very few files and its easy to manually use gcc to compile the code. But when the code grows,
Its difficult to handle build manually. So, now, we can create a makefile to build the code
2 Creating Makefile
we will put the same command used to build previously, but with little modifications.
I will say little enhancements, like bellow
Contents of Makefile
hello : ../include/hello.h ../src/hello_func.c ../test/hello.c
gcc -I ../include/ ../src/hello_func.c ../test/hello.c -o hello.out
hello : This is the Rule name
What ever following after the ‘:’ are the dependencies to be checked for.
Means, presence of these files will be checked before running the rule
Next line, starts with TAB. This defines actually what has to be run
Now, we can build the code using makefile by running the command ‘make’
3 Enhancing the Makefile
Now, we can take our makefile to the next step. Enhancements.
Still our code is very simple. We just have evry few files, so we can write the names manually.
What if the number of files is getting increased? We should make the Makefile easy to manage.
Contents of Makefile
PROJECT_NAME = hello
COMPILER = gcc
INCLUDE_DIR = ../include
TEST_DIR = ../test
SRC_DIR = ../src
EXECUTABLE_NAME = hello.out
SRC_FILES = ${SRC_DIR}/hello_func.c
TEST_FILES = ${TEST_DIR}/hello.c
INCLUDE_FILES = ${INCLUDE_DIR}/hello.h
${EXECUTABLE_NAME} : ${INCLUDE_FILES} ${SRC_FILES} ${TEST_FILES}
${COMPILER} -I ${INCLUDE_DIR} ${SRC_FILES} ${TEST_FILES} -o ${EXECUTABLE_NAME}
We are aliasing the names in more readable forms by assigning it to some variables or defines.
Now we can build using make command