I came to realize that for a system to be built in a robust and reliable fashion, I needed to automate everything that goes into the build process. This requires some concentration up front, just like writing a program requires concentration, but the payoff is that you solve the problems once, and you rely on your build configuration to take care of the details from then on. Its a variation of the fundamental programming principle of abstraction: We raise ourselves up from the grinding details by hiding those details inside a process and giving that process a name. For many years, the name of that process was make.
The make utility appeared along with C as a tool to create the Unix operating system. makes primary function is to compare the date of two files and to perform some operation that will bring those two files up-to-date with each other. The relationships between all the files in your projects and the rules necessary to bring them up-to-date (the rule is usually running the C/C++ compiler on a source file) are contained in a makefile. The programmer creates a makefile containing the description of how to build the system. When you want to bring the system up-to-date, you simply type make at the command line. To this day, installing Unix/Linux programs consists of unpacking them and typing make commands.