make

From Wikibooks, the open-content textbooks collection

Jump to: navigation, search

make is a utility for building applications. This tutorial will teach you how to use this utility with Makefiles. This tutorial is primarily focused on GNU make.

Contents

[edit] Hand compilation

The most common thing is hand compilation. You may get away with one to five source files, but having more will waste your time. A simple compilation process would be by executing this code by hand:

g++ -o file file.cpp

For newbies, this might take a while to get used to. Also, there's an alternative, using make:

make file

Both commands will do the same thing - take the file.cpp source file, compile it and then link it into an executable. But where the problem comes in is where the user has to use more than one source file, or is dependent on libraries. Making an SDL application will consist of anything like this:

g++ `sdl-config --cflags` -o file file.cpp

This is getting harder to remember, isn't it? Let's add some optimisation:

g++ -O3 -fomit-frame-pointer `sdl-config --cflags` -o file file.cpp

Ok, now I guess that you really don't want to do this way anymore. Here comes make - it will save your time!

[edit] Basics

A make file works as a simple dependency tree - it does compile the stuff that is outdated and then links your software together. You will have to specify the compilation options, but they will not be as tough on you anymore. A simple makefile for compiling your application:

default: myapp
myapp:
	g++ -o file file.cpp

To compile your application, you may do:

make

or:

make myapp

Well, you may now ask, how much of use is this? I can make a shell script for this myself! So lets now work on multiple files and object files - your application is big enough to be linked now: it contains five files.

[edit] The test case

Globally, there are three functions present:

int main(); (file1.cpp)
void file2function(std::string from); (file2.cpp)
void file3function(std::string from); (file3.cpp)

File2 and file3 have their header files, so they could be inter-linked. The actual application will look like this:

file1.cpp

#include "file2.h"
#include "file3.h"
int main()
{
	file2function("main");
	file3function("main");
};

file2.h

#include <string>
#include <iostream>
#include "file3.h"
void file2function(std::string source);

file2.cpp

#include "file2.h"
void file2function(std::string from)
{
	std::cout << "File 2 function was called from " << from << std::endl;
	file3function("file2");
};

file3.h

#include <string>
#include <iostream>
#include "file2.h"
void file3function(std::string source);

file3.cpp

#include "file3.h"
void file3function(std::string from)
{
	std::cout << "File 3 function was called from " << from << std::endl;
};

So, how would I link this all up? Well, the leetest way is to do it all by hand:

g++ -c -o file2.o file2.cpp
g++ -c -o file3.o file3.cpp
g++ -o file1 file1.cpp file2.o file3.o

However, make would offer a simpler way, Makefile:

default: testcase
testcase: file2.o file3.o
	g++ -o file1 file1.cpp file2.o file3.o

Pretty different, eh? There's a different approach to do this, which is what makes make so good:

COMPILER=g++
OBJS=file1.o file2.o file3.o
default: testcase
testcase: $(OBJS)
	$(COMPILER) -o file1 $(OBJS)

How easy is it to expand now? Just add a file to the OBJS list and you're done!

[edit] Further reading