So still, why do you need make?





It all started, it would seem, with a simple question that first led me into a stupor - "Why do I need to make? Why can not I get along with bash scripts?". And I thought - Really, why do I need make? (and most important) What problems does he solve?







Then I decided to think a bit - how would we collect our projects if we did not have make. Let's say we have a project with source codes. From them you need to get an executable file (or library). At first glance, the task seems to be simple, but we went further. Let the project initially consist of one file.









To compile it, just run one command:







$ gcc main.c -o main
      
      





It was pretty simple. But some time passes, the project develops, some modules appear in it and the source files become larger.









To compile, you need to conditionally execute the following number of commands:







 $ gcc -c src0.c $ gcc -c src1.c $ gcc -c main.c $ gcc -o main main.o src0.o src1.o
      
      





Agree, this is a rather lengthy and painstaking process. I would not do this manually. I would think that this process can be automated by simply creating a build.sh script that contains these commands. Okay, that’s a lot easier:







 $ ./build.sh
      
      





We drove on! The project is growing, the number of source files is increasing and there are more lines in them too. We are starting to notice that compilation time has increased markedly. Here we see a significant flaw in our script - it compiles all of our 50 files with source, although we only modified one.









This will not work! Developer time is too valuable a resource. Well, we can try to modify the build script in such a way that before compilation we check the modification time of the source and object files. And compile only those sources that have been changed. And conditionally, it may look something like this:







 #!/bin/bash function modification_time { date -r "$1" '+%s' } function check_time { local name=$1 [ ! -e "$name.o" ] && return $? [ "$(modification_time "$name.c")" -gt "$(modification_time "$name.o")" ] && return $? } check_time src0 && gcc -c src0.c check_time src1 && gcc -c src1.c check_time main && gcc -c main.c gcc -o main main.o src0.o src1.o
      
      





And now only those sources that have been modified will be compiled.









But what happens when the project turns into something like this:













Sooner or later, a moment will come when it will be very difficult to understand the project and the support of such scripts in itself will become a laborious process. And not the fact that this script will adequately check all the dependencies. In addition, we can have several projects and each will have its own script for assembly.







Of course, we see that a general solution to this problem arises. A tool that would provide a mechanism for checking dependencies. And here we are slowly getting to the invention of make . And now, knowing what problems we will face in the process of building the project, in the end I would formulate the following requirements for make:









Makefile



Makefiles are used to describe project assembly rules. Creating a Makefile, we declaratively describe a certain state of relations between files. The declarative nature of the state determination is convenient in that we say that we have a list of files and we need to get a new file from them by executing a list of commands. In the case of using some imperative language (for example, shell), we would have to perform a large number of different checks, getting complex and confusing code, while make does it for us. The main thing is to build the right dependency tree.







 <  > : <  ... > <  > ... ...
      
      





I will not talk about how to write Makefiles. There are a lot of manuals on the Internet on this subject and you can turn to them if you wish. And besides, few people write Makefiles manually. And very complex Makefiles can be a source of complications instead of simplifying the build process.








All Articles