HTML Diff
0 added 0 removed
Original 2026-01-01
Modified 2026-02-21
1 <h2>Introduction</h2>
1 <h2>Introduction</h2>
2 <p>Many developers may recall the first day they started working on a new project. After cloning the main repository, there comes a point when you have to enter a lot of commands with certain flags and in a specific order. In most cases, it’s hard to grasp what is going on without a description of the commands. For example:</p>
2 <p>Many developers may recall the first day they started working on a new project. After cloning the main repository, there comes a point when you have to enter a lot of commands with certain flags and in a specific order. In most cases, it’s hard to grasp what is going on without a description of the commands. For example:</p>
3 <p>These commands are just a small portion of the project deployment process. The commands themselves are extensive and contain several flags, as shown in the example above, making them not only difficult to learn but also difficult to enter manually. Constantly maintaining documentation becomes more challenging as the project grows; it inevitably becomes outdated, and the entry barrier for newcomers increases since no one can remember all of the project's details. Some of these commands must be used on a daily basis, if not multiple times per day.</p>
3 <p>These commands are just a small portion of the project deployment process. The commands themselves are extensive and contain several flags, as shown in the example above, making them not only difficult to learn but also difficult to enter manually. Constantly maintaining documentation becomes more challenging as the project grows; it inevitably becomes outdated, and the entry barrier for newcomers increases since no one can remember all of the project's details. Some of these commands must be used on a daily basis, if not multiple times per day.</p>
4 <p>Over time, it became clear that we desperately needed a tool that could maintain such commands, and provide convenient shortcuts and self-documentation of the project. This is precisely what<em>Makefile</em>and the make utility have turned into. In this guide, I'll show you how to reduce the deployment to a few short and straightforward commands using these tools:</p>
4 <p>Over time, it became clear that we desperately needed a tool that could maintain such commands, and provide convenient shortcuts and self-documentation of the project. This is precisely what<em>Makefile</em>and the make utility have turned into. In this guide, I'll show you how to reduce the deployment to a few short and straightforward commands using these tools:</p>
5 <h2>What is make and<em>Makefile</em></h2>
5 <h2>What is make and<em>Makefile</em></h2>
6 <p><em>Makefile</em>is a file that is stored in the repository alongside the code. It is usually placed at the project’s root. It acts both as documentation and as executable code. The Makefile hides the implementation details and manages the commands, and the make utility runs them from the Makefile in the current directory.</p>
6 <p><em>Makefile</em>is a file that is stored in the repository alongside the code. It is usually placed at the project’s root. It acts both as documentation and as executable code. The Makefile hides the implementation details and manages the commands, and the make utility runs them from the Makefile in the current directory.</p>
7 <p>make was originally designed to automate the building process of executable programs and libraries from source code. Most *nix distributions have it by default, which has contributed to its extensive use. Later, it turned out that this tool is convenient to use in other development projects because the process is essentially the same in most cases - automation and building applications.</p>
7 <p>make was originally designed to automate the building process of executable programs and libraries from source code. Most *nix distributions have it by default, which has contributed to its extensive use. Later, it turned out that this tool is convenient to use in other development projects because the process is essentially the same in most cases - automation and building applications.</p>
8 <p>The make has become a standard for many developers, especially for those working on large projects. Examples of makefile can be found in projects such as<a>Kubernetes</a>,<a>Babel</a>,<a>Ansible</a>, and, of course, everywhere on<a>Hexlet</a>.</p>
8 <p>The make has become a standard for many developers, especially for those working on large projects. Examples of makefile can be found in projects such as<a>Kubernetes</a>,<a>Babel</a>,<a>Ansible</a>, and, of course, everywhere on<a>Hexlet</a>.</p>
9 <h3><em>Makefile</em>syntax</h3>
9 <h3><em>Makefile</em>syntax</h3>
10 <p>make runs targets from a<em>Makefile</em>that contains the following commands:</p>
10 <p>make runs targets from a<em>Makefile</em>that contains the following commands:</p>
11 <p>However, it's not enough to just start using a Makefile in a project. To make its implementation more efficient, build a target-oriented command structure and give the targets semantically relevant names. At first, moving commands to a Makefile may result in all commands being merged into a single one with a vague name:</p>
11 <p>However, it's not enough to just start using a Makefile in a project. To make its implementation more efficient, build a target-oriented command structure and give the targets semantically relevant names. At first, moving commands to a Makefile may result in all commands being merged into a single one with a vague name:</p>
12 <p>Several actions take place here at once: creating a file with environment variables, preparing the database, generating keys, installing dependencies, and launching the project. Since this is impossible to understand from the comments and target name, it’s best to separate these commands into different independent targets:</p>
12 <p>Several actions take place here at once: creating a file with environment variables, preparing the database, generating keys, installing dependencies, and launching the project. Since this is impossible to understand from the comments and target name, it’s best to separate these commands into different independent targets:</p>
13 <p>Now that the commands are divided into targets, you can individually install dependencies with the make install command or run your app via make start. But the remaining targets are only required during the project's initial deployment and must be performed in a specific sequence. In the Makefile world, the target has the following prerequisites:</p>
13 <p>Now that the commands are divided into targets, you can individually install dependencies with the make install command or run your app via make start. But the remaining targets are only required during the project's initial deployment and must be performed in a specific sequence. In the Makefile world, the target has the following prerequisites:</p>
14 <p>Commands will only be executed in the specified order and only if the previous command proves to be successful. Therefore, you can add a setup target to combine all the necessary actions:</p>
14 <p>Commands will only be executed in the specified order and only if the previous command proves to be successful. Therefore, you can add a setup target to combine all the necessary actions:</p>
15 <p>Now it is enough to deploy and launch the project with two commands:</p>
15 <p>Now it is enough to deploy and launch the project with two commands:</p>
16 <p>The project commands and flags are combined into a<em>Makefile</em>as a result of the<em>Makefile's</em>work. It ensures the correct execution order, regardless of the languages or technologies involved.</p>
16 <p>The project commands and flags are combined into a<em>Makefile</em>as a result of the<em>Makefile's</em>work. It ensures the correct execution order, regardless of the languages or technologies involved.</p>
17 <h2>Advanced usage</h2>
17 <h2>Advanced usage</h2>
18 <h3>Fake target</h3>
18 <h3>Fake target</h3>
19 <p>Using make in a project may one day lead to the error make: &lt;target name&gt; is up to date., although everything is written correctly. This is frequently related to the existence of a directory or file that matches the target name. For example:</p>
19 <p>Using make in a project may one day lead to the error make: &lt;target name&gt; is up to date., although everything is written correctly. This is frequently related to the existence of a directory or file that matches the target name. For example:</p>
20 <p>As stated previously, make was designed to build programs from source code. Therefore, it searches for a directory or file with the given name and attempts to create a project from it. To alter this behavior, you need to add a .PHONY pointer to the target at the end of the Makefile:</p>
20 <p>As stated previously, make was designed to build programs from source code. Therefore, it searches for a directory or file with the given name and attempts to create a project from it. To alter this behavior, you need to add a .PHONY pointer to the target at the end of the Makefile:</p>
21 <h3>Running commands consecutively and ignoring errors</h3>
21 <h3>Running commands consecutively and ignoring errors</h3>
22 <p>You can run commands one at a time: make setup, make start, make test or all at once, space-separated: make setup start test. The latter method works as a dependency between commands, although it is not documented in the Makefile. Difficulties may arise if one of the commands produces an error that must be ignored. In the previous examples, such a command was to create an .env-file when deploying the project:</p>
22 <p>You can run commands one at a time: make setup, make start, make test or all at once, space-separated: make setup start test. The latter method works as a dependency between commands, although it is not documented in the Makefile. Difficulties may arise if one of the commands produces an error that must be ignored. In the previous examples, such a command was to create an .env-file when deploying the project:</p>
23 <p>The easiest (<em>but not the only</em>) way to "cover up” an error is to use a logical OR in the Makefile:</p>
23 <p>The easiest (<em>but not the only</em>) way to "cover up” an error is to use a logical OR in the Makefile:</p>
24 <p>Be cautious applying such hacks so that you don't shoot yourself in the foot in more complex scenarios.</p>
24 <p>Be cautious applying such hacks so that you don't shoot yourself in the foot in more complex scenarios.</p>
25 <h3>Variables</h3>
25 <h3>Variables</h3>
26 <p>Configuration parameters, path indicators, and environment variables are often substituted into commands, and make enables you to handle this as well. Variables can be written directly in the command within the makefile and passed when called:</p>
26 <p>Configuration parameters, path indicators, and environment variables are often substituted into commands, and make enables you to handle this as well. Variables can be written directly in the command within the makefile and passed when called:</p>
27 <p>Variables can be optional and have a default value. They are commonly declared at the beginning of the Makefile.</p>
27 <p>Variables can be optional and have a default value. They are commonly declared at the beginning of the Makefile.</p>
28 <p>Some variables in the<em>Makefile</em>have names other than the system ones. For example, $PWD is referred to as $CURDIR in the<a>Makefile</a>:</p>
28 <p>Some variables in the<em>Makefile</em>have names other than the system ones. For example, $PWD is referred to as $CURDIR in the<a>Makefile</a>:</p>
29 <h2>Conclusion</h2>
29 <h2>Conclusion</h2>
30 <p>In this guide, we covered the main features of<em>Makefile</em>and the make utility. A deeper understanding of this tool will reveal many of its other useful features, such as conditions, cycles, and importing files. Makefile will be a great help in standardizing generic instructions in companies where multiple projects are written by different teams at different times: setup start test deploy ....</p>
30 <p>In this guide, we covered the main features of<em>Makefile</em>and the make utility. A deeper understanding of this tool will reveal many of its other useful features, such as conditions, cycles, and importing files. Makefile will be a great help in standardizing generic instructions in companies where multiple projects are written by different teams at different times: setup start test deploy ....</p>
31 <p>Because the Makefile can describe multi-line commands consecutively, it may be used as a "universal glue" between language managers and other utilities. The widespread use of this tool and its overall simplicity allows you to quickly implement it into your project without making any changes. However, Makefile can be extremely large and complicated, as shown by the following real-world applications:</p>
31 <p>Because the Makefile can describe multi-line commands consecutively, it may be used as a "universal glue" between language managers and other utilities. The widespread use of this tool and its overall simplicity allows you to quickly implement it into your project without making any changes. However, Makefile can be extremely large and complicated, as shown by the following real-world applications:</p>
32 <ul><li><a>Codebattle</a></li>
32 <ul><li><a>Codebattle</a></li>
33 <li><a>Babel</a></li>
33 <li><a>Babel</a></li>
34 <li><a>Kubernetes</a></li>
34 <li><a>Kubernetes</a></li>
35 </ul><h3>Additional materials</h3>
35 </ul><h3>Additional materials</h3>
36 <ul><li><a>Modern Make Handbook</a>- a summary of the documentation</li>
36 <ul><li><a>Modern Make Handbook</a>- a summary of the documentation</li>
37 </ul><p>Makefile examples from this guide were taken from:</p>
37 </ul><p>Makefile examples from this guide were taken from:</p>
38 <ul><li><a>Hexlet SICP</a></li>
38 <ul><li><a>Hexlet SICP</a></li>
39 <li><a>Hexlet Basics</a></li>
39 <li><a>Hexlet Basics</a></li>
40 </ul>
40 </ul>