Makefile for the smallest

  • Tutorial
Not very strict translation of the material mrbook.org/tutorials/make At one time I really didn’t have enough such a training manual to understand the basic things about make. I think it will be at least interesting to anyone. Although this technology is dying, it is still used in so many projects. There wasn’t enough karma for the “Transfers” hub, as soon as the opportunity arises - I’ll add there too. Added to Translations. If there are errors in design, then please indicate them. I will correct it.

The article will be interesting primarily for those studying C / C ++ programming in UNIX-like systems from the very roots, without using an IDE.

Compiling a project with pens is a tedious task, especially when there are more than one source file, and for each of them you need to type compilation and linking commands each time. But it is not all that bad. Now we will learn how to create and use makefiles. A makefile is a set of instructions for a make program that helps you build a software project in just one touch.

For practice, you will need to create a microscopic project a la Hello World from four files in one directory:
main.cpp
#include 
#include "functions.h"
using namespace std;
int main(){
    print_hello();
    cout << endl;
    cout << "The factorial of 5 is " << factorial(5) << endl;
    return 0;
}


hello.cpp
#include 
#include "functions.h"
using namespace std;
void print_hello(){
   cout << "Hello World!";
}


factorial.cpp
#include "functions.h"
int factorial(int n){
    if(n!=1){
	return(n * factorial(n-1));
    }
    else return 1;
}


functions.h
void print_hello();
int factorial(int n);


Everything can be downloaded in bulk from here.
The author used the C ++ language, which is not necessary to know, and the g ++ compiler from gcc. Any other compiler is likely to do the same. Files slightly tweaked so gcc 4.7.1 builds

Make program

If you start,
make
the program will try to find the file with the default name Makefilein the current directory and follow the instructions from it. If there are several makefiles in the current directory, then you can specify the one you need in this way:
make -f MyMakefile
There are many other parameters that we do not need so far. You can find out about them in the man page.

Assembly process

The compiler takes the source code files and obtains object files from them. The linker then takes the object files and obtains an executable file from them. Assembly = compilation + linking.

Hand compilation

The easiest way to build a program:
g++ main.cpp hello.cpp factorial.cpp -o hello
Each time typing is inconvenient, so we will automate it.

The easiest makefile

It should include the following parts:
цель: зависимости
[tab] команда

For our example, the makefile would look like this:
all:
	g++ main.cpp hello.cpp factorial.cpp -o hello

Please note that the line with the command must begin with a tab! Save this under the name Makefile-1in the project directory and start the assembly with the command. make -f Makefile-1
In the first example, the target is called all. This is the default target for the makefile, which will be executed if no other target is explicitly specified. Also for this purpose in this example there are no dependencies, so make immediately starts to execute the necessary command. And the team, in turn, starts the compiler.

Using Dependencies

Using multiple targets in one makefile is useful for large projects. This is due to the fact that when changing one file, you don’t need to reassemble the entire project, but you can do without reassembling only the changed part. Example:
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

This must be saved under the name Makefile-2everything in the same directory.

Now the target allhas only a dependency, but no command. In this case, make, upon invocation, will sequentially execute all the dependencies specified in the file for this purpose.
Another added goal clean. It is traditionally used for quick cleaning of all project assembly results. Cleaning starts like this:make -f Makefile-2 clean

Using Variables and Comments

Variables are widely used in makefiles. For example, this is a convenient way to take into account the possibility that the project will be assembled by another compiler or with other options.
# Это комментарий, который говорит, что переменная CC указывает компилятор, используемый для сборки
CC=g++
#Это еще один комментарий. Он поясняет, что в переменной CFLAGS лежат флаги, которые передаются компилятору
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

This Makefile-3
Variables is a very convenient thing. To use them, you just need to assign them a value until they are used. After that, you can substitute their value in the right place in this way:$(VAR)

What to do next

After this brief briefing, you can already try to create simple makefiles yourself. Next you need to read serious textbooks and manuals. As a final chord, you can try to independently disassemble and realize such a universal makefile that can be adapted with just two touches for almost any project:
CC=g++
CFLAGS=-c -Wall
LDFLAGS=
SOURCES=main.cpp hello.cpp factorial.cpp
OBJECTS=$(SOURCES:.cpp=.o)
EXECUTABLE=hello
all: $(SOURCES) $(EXECUTABLE)
$(EXECUTABLE): $(OBJECTS) 
	$(CC) $(LDFLAGS) $(OBJECTS) -o $@
.cpp.o:
	$(CC) $(CFLAGS) $< -o $@

Makefile-4
Good luck!

Also popular now: