⬆️ ⬇️

Makefile for the smallest

Not very strict translation of the material mrbook.org/tutorials/make At one time, I really didn’t have enough such a manual for understanding basic things about make. I think it will be at least interesting to someone. Although this technology is dying off, it is still used in very many projects. Karma on the hub "Transfers" was not enough, as soon as the opportunity arises - I will add there too. Added to Translations. If there are errors in the design, please indicate them. I will correct.



The article will be interesting first of all to students programming in C / C ++ on UNIX-like systems from the very roots, without using IDE.



Compiling a project with handles is a tedious task, especially when the source files become more than one, and for each of them you need to compile and link commands each time. But it is not all that bad. Now we will learn to create and use makefiles. A makefile is a set of instructions for the make program that helps you build a software project with just one touch.



To practice, you will need to create a microscopic project a la Hello World from four files in one directory:

main.cpp
#include <iostream> #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 <iostream> #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); 




All in a crowd can be downloaded from here.

The author used the C ++ language, which is not necessary to know, and the g ++ compiler from gcc. Any other compiler is also likely to work. Files slightly tweaked for gcc 4.7.1 to build

')

Make program


If you run

make

the program will try to find the file with the name of the default Makefile in the current directory and execute instructions from it. If there are several makefiles in the current directory, you can point to the necessary one like this:

make -f MyMakefile

There are many other parameters that we do not need. You can find out about them in the man page.



Assembly process


The compiler takes the source code files and retrieves the object files from them. Then the linker takes the object files and gets the executable file from them. Build = compile + link.



Compiling hands


The easiest way to build a program:

g++ main.cpp hello.cpp factorial.cpp -o hello

Each time it is inconvenient to type, so we will automate.



The easiest Makefile


It should have the following parts:

 :  [tab]  


For our example, the makefile will look like this:

 all: g++ main.cpp hello.cpp factorial.cpp -o hello 


Please note that the line with the command must start with a tab! Save it as Makefile-1 in the project directory and start the build with the command make -f Makefile-1

In the first example, the target is all . This is the default target for the makefile, which will be executed if no other target is specified explicitly. Also, this goal has no dependencies in this example, so make immediately starts to execute the desired command. And the command in turn starts the compiler.



Dependency usage


Using multiple targets in the same makefile is useful for large projects. This is due to the fact that when changing a single file, you do not need to rebuild the entire project, and it will be possible to manage to reassemble only the modified 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 should be saved under the name Makefile-2 all in the same directory



Now all has only a dependency, but no command. In this case, make, when invoked, will consistently perform all the dependencies in the file for this target.

A new clean target has been added. It is traditionally used to quickly clean up all project build 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 consider the possibility that a project will be built 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 is a Makefile-3

Variables are very handy. To use them you just need to assign them a value before they are used. After that, you can substitute their value in the right place in this way: $(VAR)



What to do next


After this briefing, you can already try creating simple makefiles yourself. Further it is necessary to read serious textbooks and manuals. As a final chord, you can try to independently disassemble and realize such a universal makefile, which can be adapted to almost any project in two touches:

 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

Successes!

Source: https://habr.com/ru/post/155201/



All Articles