===== Makefile ===== Running the command make causes a search for a file called //Makefile// or //makefile// in your directory and then execute it. In case you have several makefiles, you can specify one as: make -f MyMakefile === Basic Makefile === The build process contains two steps; - Compiler takes the source file and outputs the object files - Linker takes the object files and creates an executable The basic makefile is composed of: target: dependencies [tab] system command By default, the goal is the first target in the makefile (not counting targets that start with a period). Therefore, //makefiles// are usually written so that the first target is for compiling the entire program or programs they describe. If the first rule in the //makefile// has several targets, only the first target in the rule becomes the default goal, not the whole list. The default target for //makefiles// is called //all//. In a simple case the target //all// has no dependencies: all: g++ main.cpp hello.cpp factorial.cpp -o hello In some cases it is useful to have different targets. This way, you don't need to recompile everything after modifying a single file: all: hello hello: main.o factorial.o hello.o g++ main.o factorial.o hello.o -o hello main.o: main.cpp g++ -c main.cpp factorial.o: factorial.cpp g++ -c factorial.cpp hello.o: hello.cpp g++ -c hello.cpp clean: rm -rf *o hello In order to for make to execute correctly, it has to meet all the dependencies of the //all// target. It is very useful to have a //clean// target to get rid of all the object files and executables quickly. === Using variables === You can also use variables in your //Makefiles//. They are very helpful particularly when you want to change the compiler, or the compiler options. The variables are defined at the beginning of a //makefile//. CC=g++ CFLAGS=-c -Wall all: hello hello: main.o factorial.o hello.o $(CC) main.o factorial.o hello.o -o hello main.o: main.cpp $(CC) $(CFLAGS) main.cpp factorial.o: factorial.cpp $(CC) $(CFLAGS) factorial.cpp hello.o: hello.cpp $(CC) $(CFLAGS) hello.cpp clean: rm -rf *o hello There are some variables already prescribed and available; for more info have a look at this page: [[https://www.gnu.org/software/make/manual/html_node/Automatic-Variables.html]] === Searching Directories for Prerequisites === It is often desirable to put sources in a separate directory from the binaries. The directory search features of //make// facilitate this by searching several directories automatically to find a prerequisite. The value of the //make// variable VPATH specifies a list of directories that //make// should search. VPATH specifies a search list that //make// applies for all files, including files which are targets of rules. In the VPATH variable, directory names are separated by colons or blanks. The order in which directories are listed is the order followed by //make// in its search. For example, VPATH = src:../headers specifies a path containing two directories, //src// and //../headers//, which //make// searches in that order. With this value of VPATH, the following rule, foo.o : foo.c is interpreted as if it was written like: foo.o : src/foo.c assuming the file //foo.c// does not exist in the current directory but is found in the directory //src//. === Phony targets === A phony target is one that is not really the name of a file. It is just a name for some commands to be executed when you make an explicit request. There are two reasons to use a phony target: to avoid a conflict with a file of the same name, and to improve performance. If you write a rule whose commands will not create the target file, the commands will be executed every time the target comes up for remaking. Here is an example: clean: rm *.o temp Because the rm command does not create a file named //clean//, probably no such file will ever exist. Therefore, the rm command will be executed every time you say //make clean//. The phony target will cease to work if anything ever does create a file named //clean// in this directory. Since it has no prerequisites, the file //clean// would inevitably be considered up to date, and its commands would not be executed. To avoid this problem, you can explicitly declare the target to be phony, using the special target //.PHONY// as follows: .PHONY : clean clean: rm *.o temp Once this is done, //make clean// will run the commands regardless of whether there is a file named //clean//. Since it knows that phony targets do not name actual files that could be remade from other files, make skips the implicit rule search for phony targets. This is why declaring a target phony is good for performance, even if you are not worried about the actual file existing.