summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAki <please@ignore.pl>2023-03-27 22:36:21 +0200
committerAki <please@ignore.pl>2023-03-27 22:36:21 +0200
commite683f80bb5a847cc11251c45ff8b9553826b6eb5 (patch)
tree243e2d62e694a71c75d1d9aaf5eb946e2cdfa31b
parentea823149b20e9c3bec66369a5480353e48869279 (diff)
downloadignore.pl-e683f80bb5a847cc11251c45ff8b9553826b6eb5.zip
ignore.pl-e683f80bb5a847cc11251c45ff8b9553826b6eb5.tar.gz
ignore.pl-e683f80bb5a847cc11251c45ff8b9553826b6eb5.tar.bz2
Rewrote make introduction post
-rw-r--r--aliases.map1
-rw-r--r--graveyard_of_the_drawings-12.pngbin0 -> 1159 bytes
-rw-r--r--graveyard_of_the_drawings-13.png (renamed from the_gentlest_introduction_to_building_with_makefiles-1.png)bin982 -> 982 bytes
-rw-r--r--graveyard_of_the_drawings.html3
-rw-r--r--how_to_build_software_with_make-1.png (renamed from the_gentlest_introduction_to_building_with_makefiles-3.png)bin1941 -> 1941 bytes
-rw-r--r--how_to_build_software_with_make-2.png (renamed from the_gentlest_introduction_to_building_with_makefiles-2.png)bin1158 -> 1158 bytes
-rw-r--r--how_to_build_software_with_make.html210
-rw-r--r--index.html7
-rw-r--r--the_gentlest_introduction_to_building_with_makefiles.html239
9 files changed, 217 insertions, 243 deletions
diff --git a/aliases.map b/aliases.map
index e68eaab..122ea87 100644
--- a/aliases.map
+++ b/aliases.map
@@ -8,3 +8,4 @@
/self_update_sine.html /self_update_march_2023.html;
/how_to_create_generic_interfaces_by_example_of_storing_files_in_arbitrary_memory.html /playing_around_with_simple_interfaces.html;
/how_to_create_templates_with_shell_cat_and_envsubst.html /how_to_generate_files_from_templates_in_shell.html;
+/the_gentlest_introduction_to_building_with_makefiles.html /how_to_build_software_with_make.html;
diff --git a/graveyard_of_the_drawings-12.png b/graveyard_of_the_drawings-12.png
new file mode 100644
index 0000000..d390eac
--- /dev/null
+++ b/graveyard_of_the_drawings-12.png
Binary files differ
diff --git a/the_gentlest_introduction_to_building_with_makefiles-1.png b/graveyard_of_the_drawings-13.png
index 768e52e..768e52e 100644
--- a/the_gentlest_introduction_to_building_with_makefiles-1.png
+++ b/graveyard_of_the_drawings-13.png
Binary files differ
diff --git a/graveyard_of_the_drawings.html b/graveyard_of_the_drawings.html
index 55bee17..b7e3ba5 100644
--- a/graveyard_of_the_drawings.html
+++ b/graveyard_of_the_drawings.html
@@ -13,7 +13,7 @@
<article>
<h1>Graveyard of the Drawings</h1>
-<p class="subtitle">Last modified on 2023-03-26 18:05+02:00
+<p class="subtitle">Last modified on 2023-03-27 22:35+02:00
<p>Here are the drawings I made for articles that I decided to remove. No context, no nothing. Just images. Despite
the style, I still think that it'd be a little bit of waste to just remove them along the texts and reusing them in
different articles is just lazy.</p>
@@ -29,4 +29,5 @@ different articles is just lazy.</p>
<img src="graveyard_of_the_drawings-10.png">
<img src="graveyard_of_the_drawings-11.png">
<img src="graveyard_of_the_drawings-12.png">
+<img src="graveyard_of_the_drawings-13.png">
</article>
diff --git a/the_gentlest_introduction_to_building_with_makefiles-3.png b/how_to_build_software_with_make-1.png
index 0c1afb9..0c1afb9 100644
--- a/the_gentlest_introduction_to_building_with_makefiles-3.png
+++ b/how_to_build_software_with_make-1.png
Binary files differ
diff --git a/the_gentlest_introduction_to_building_with_makefiles-2.png b/how_to_build_software_with_make-2.png
index 79250c7..79250c7 100644
--- a/the_gentlest_introduction_to_building_with_makefiles-2.png
+++ b/how_to_build_software_with_make-2.png
Binary files differ
diff --git a/how_to_build_software_with_make.html b/how_to_build_software_with_make.html
new file mode 100644
index 0000000..dce05aa
--- /dev/null
+++ b/how_to_build_software_with_make.html
@@ -0,0 +1,210 @@
+<!doctype html>
+<html lang="en">
+<meta charset="utf-8">
+<meta name="viewport" content="width=device-width, initial-scale=1">
+<meta name="author" content="aki">
+<meta name="tags" content="tutorial, make, building, compiling, C">
+<link rel="icon" type="image/png" href="favicon.png">
+<link rel="stylesheet" href="style.css">
+
+<title>How to Build Software With Make</title>
+
+<nav><p><a href="https://ignore.pl">ignore.pl</a></p></nav>
+
+<article>
+<h1>How to Build Software With Make</h1>
+<p class="subtitle">Published on 2023-03-21 20:00:00+02:00
+<p>To compile an executable from a single C source file we need just one compiler invocation in our shell:
+<pre>
+$ cc myprogram.c -o myprogram
+$ ./myprogram
+Hello, World!
+</pre>
+<p>As we expand our projects they naturally become harder to build. If not due to dependencies then due to pure
+repetitiveness of the task. <a href="https://en.wikipedia.org/wiki/Build_automation">Build systems</a> are a response to
+that and <a href="https://www.gnu.org/software/make/">GNU Make</a> is one of them. GNU Make is part of a larger family
+of programs that usually share the <b>make</b>(1) (or similar, e.g., nmake, mk). Although timeline doesn't necessarily
+agree, we can say that <b>make</b> is defined in
+<a href="https://pubs.opengroup.org/onlinepubs/9699919799/utilities/make.html">POSIX standard</a>.
+<p>Principles of Make are straight-forward: as a user we define a set of rules that consist of targets, dependencies and
+commands. Targets are usually filenames that describe what rule is expected to produce. Dependencies are names of other
+targets or source files. That's it. Later this concept is expanded upon to reduce the amount of lines we need to write.
+<p>When we build native software we are mainly interested in:
+<ul>
+<li>Executables (e.g., ELF, PE *.exe)
+<li>Static libraries (e.g., *.a, *.lib)
+<li>Dynamic/shared libraries (e.g., *.so, *.dll)
+</ul>
+<p>Since <b>make</b> live close to the compiler we will be also interested in object files (e.g., *.o, *.obj).
+
+<h2>How to Build Executables With Make</h2>
+<p><b>Make<b> helps us to reduce number of characters we need to type in terminal and lines we need to put to setup the
+build. In fact, the simplest case of one source file to one executable, like the one I showed above, does not need any
+preparation at all:
+<pre>
+$ make myprogram
+cc myprogram.c -o myprogram
+$ ./myprogram
+Hello, World!
+</pre>
+<p>First thing that we should observe is that <b>make</b> nonchalantly prints the commands it executes to build stuff
+for us. I'll keep them visible in samples so it's hopefully more clear what's happening.
+<p>We invoke <b>make</b> directly with a name of the target we intend to build. Remember: targets are usually filenames
+that are expected to be produced by a rule. Based on the target name and built-in rules <b>make</b> guesses what to do
+to get <i>myprogram</i>. It finds <i>myprogram.c</i> in the working directory and selects an appropriate rule.
+<p>Yet, we still need to type the target name each time we want to build it. We can avoid it by creating a file called
+<i>Makefile</i> in the project directory. This is the file containing all build rules and other helpful definitions. If
+<b>make</b> is ran without any targets then the first target found in <i>Makefile</i> is used. Consider <i>Makefile</i>:
+<pre>
+myprogram:
+</pre>
+<p>Let's try it:
+<pre>
+$ make
+cc myprogram.c -o myprogram
+</pre>
+<p>Selects the first and the only target as intended.</p>
+<img src="how_to_build_software_with_make-1.png" alt="broom">
+<p>There are <a href="https://www.gnu.org/software/make/manual/html_node/Standard-Targets.html">traditional targets</a>
+that users of our makefiles may expect. A less bare-bone makefile would look like this:
+<pre>
+all: myprogram
+clean:
+ rm -f myprogram
+.PHONY: all clean
+</pre>
+<p>Now, someone can run following to ensure that a clean build is made:
+<pre>
+$ make clean all
+rm -f myprogram
+cc myprogram.c -o myprogram
+</pre>
+<p>Let's note that we can specify multiple targets in the command line. They will be build in order.
+<p>Next, <code>all: myprogram</code> - this notation specifies that target <i>all</i> depends on <i>myprogram</i>. We
+can specify multiple dependencies if needed. All dependencies will be built and once they are done the dependant target
+will be processed.
+<p><code>.PHONY</code> is a special target that is used to mark targets that are not expected to produce files. We are
+not expecting <i>all</i> or <i>clean</i> files to be present at any stage. Instead we can imagine these as tasks or
+actions. Other such targets would be for example <i>install</i>, <i>uninstall</i> or <i>dist</i>.
+
+<h2>How to Build Object Files With Make</h2>
+<p>Usually, we won't implement our projects inside a single source file. We want to split logical parts of the software
+into several files. Consider <i>greeting.h</i>:
+<pre>
+#pragma once
+void greet(void);
+</pre>
+<p>With accompanying <i>greeting.c</i>:
+<pre>
+#include &lt;stdio.h&gt;
+#include "greeting.h"
+void greet(void)
+{
+ printf("Hello, World!");
+}
+</pre>
+<p>And our program that uses them, let's stay with <i>myprogram.c</i>:
+<pre>
+#include "greeting.h"
+int main()
+{
+ greet();
+}
+</pre>
+<p>As simple as it gets while it still illustrates the problem.</p>
+<img src="how_to_build_software_with_make-2.png" alt="files">
+<p>When we build our program from a single source the compiler does two things: compiles and links. Now we want to do
+these separately. An intermediate result of compilation is an object file. On Linux and Unix platforms they usually use
+*.o extension. We can instruct <b>make</b> to use them by adding new rules to our existing makefile:
+<pre>
+myprogram: myprogram.o greeting.o
+myprogram.o: greeting.h
+greeting.o: greeting.h
+</pre>
+<p>First we declare that in order to build <i>myprogram</i> two object files are needed. Then we define some additional
+relationships between the object files and the only header file that we have.
+<p>Note that we did not specify explicitly dependency between the object files and the respective source files.
+Technically we could also skip the relationship between <i>myprogram</i> and <i>myprogram.o</i> and <b>make</b> would
+still figure it out. This is a matter of what we want to declare explicitly, how lazy we are at the time of writing and
+how permissive are the built-in rules that we use.
+<p>Let's try it out:
+<pre>
+$ make
+cc -c -o myprogram.o myprogram.c
+cc -c -o greeting.o greeting.c
+cc myprogram.o greeting.o -o myprogram
+$ ./myprogram
+Hello, World!
+</pre>
+
+<h2>How to Build Static Libraries With Make</h2>
+<p>The best part here is that we're pretty much already set. Static libraries are archives containing object files. They
+are created and updates using <b>ar</b>(1). There are built-in rules available for them, too, but with one additional
+gimmick. They use archive targets that look like this:
+<pre>
+myprogram: myprogram.o libgreeting.a
+libgreeting.a: libgreeting.a(greeting.o)
+</pre>
+<p>We replaced <i>greeting.o</i> prerequisite with <i>libgreeting.a</i> which is defined line below. Dependencies of the
+library target are expressed as
+<a href="https://pubs.opengroup.org/onlinepubs/9699919799/utilities/make.html#tag_20_76_13_07">archive members</a>.
+
+<h2>How to Build Shared Libraries With Make</h2>
+<p>Shared/dynamic libraries are different. The process of building them with <b>make</b> is similar to executables, but
+we want to modify compilation and linking options, and write our own command:
+<pre>
+CFLAGS=-fPIC
+LDFLAGS=-shared
+libgreeting.so: greeting.o
+ $(LD) -shared $(LDLIBS) $(LDFLAGS) $^ -o $@
+</pre>
+<p>First two lines are variable definitions (called "macros" in POSIX). We set <i>CFLAGS</i> - C compiler flags - to
+<code>-fPIC</code> to enable <a href="https://en.wikipedia.org/wiki/Position-independent_code">position-independent
+code</a>, which is needed when compiling code for shared libraries that are expected to work nicely on Linux. Then, we
+set <i>LDFLAGS</i> - linker flags - to <code>-shared</code> which (put simply) tells the linker to build a shared
+object.
+<p>Now let's analyse linker command itself. Starting with <code>$(LD)</code> which is substituted with linker
+executable. We already know <code>$(LDFLAGS)</code>, so <code>$(LDLIBS)</code> sounds like "linker libraries" and that's
+correct. Finally, we have two
+<a href="https://www.gnu.org/software/make/manual/html_node/Automatic-Variables.html">automatic variables</a> also known
+as <a href="https://pubs.opengroup.org/onlinepubs/9699919799/utilities/make.html#tag_20_76_13_08">internal
+macros</a>: <code>$^</code> (substituted by all dependencies) and <code>$@</code> (substituted by target name). Note
+that <code>$^</code> is not part of POSIX.
+<p>When we finally run <b>make</b> we will see how it performs all predicted substitutions:
+<pre>
+$ make
+cc -fPIC -c -o greeting.o greeting.c
+ld -shared greeting.o -o libgreeting.so
+</pre>
+<p>Value for <code>$(LD)</code> is provided by default by <b>make</b>.
+<p>In some cases, we may want to invoke the linker via the compiler to have all defaults implicitly defined. For example
+for C++ we would replace <code>$(LD)</code> with <code>$(CXX)</code> to imply e.g., <code>-lstdc++</code>.
+
+<h2>How to Build Against External Libraries With Make</h2>
+<p>This one starts to be tricky. The simple case where we use libraries installed in <i>/usr</i> or <i>/usr/local</i> is
+exactly that - simple. All we need to do is put linker options in a variable (macro) that we have already seen:
+<code>$(LDLIBS)</code>:
+<pre>
+LDLIBS=-llua -lm
+</pre>
+<p>Since managing these manually easily becomes a problem there are tools that can generate list of these options for
+us. One of them is <b>pkgconfig</b>(1). In most <b>make</b> implementations we can use backticks to run command and use
+its output:
+<pre>
+CFLAGS=`pkg-config --cflags lua`
+LDLIBS=`pkg-config --libs lua`
+</pre>
+<p>This will link Lua and make its headers available.
+
+<h2>What's next?</h2>
+<p>This is only a beginning. I hope it's a good overview, but the true journey awaits. This is but a dump of information
+and playing around with <b>make</b> sounds like a reasonable next step. Because of its simple design <b>make</b> is not
+limited to C, C++, yacc/bison or Fortran. I use it for most small weekend projects I do, be it RST to HTML generation or
+image rendering. Anything that can be described as processing from one file to another (or generation from thin air) is
+good enough to be put into a makefile.
+<p>Next step after playing around some is diving deeper into automatic variables and
+<a href="https://www.gnu.org/software/make/manual/html_node/Pattern-Rules.html">pattern rules</a>. I'd recommend to
+skip over <a href="https://pubs.opengroup.org/onlinepubs/9699919799/utilities/make.html#tag_20_76_13_06">inference
+rules/suffixes</a>.
+</article>
+<script src="https://stats.ignore.pl/track.js"></script>
diff --git a/index.html b/index.html
index f94b438..4949598 100644
--- a/index.html
+++ b/index.html
@@ -37,8 +37,12 @@ software and hardware engineering. I post here my projects, experiments, and wha
<section id="posts">
<h2>Posts</h2>
<ul>
+<li> <a href="how_to_build_software_with_make.html">How to Build Software With Make</a><br>
+ <i>This replaced an old post from 2020 about the same topic.</i><br>
+ <time>2023-03-27</time>
<li> <a href="how_to_generate_files_from_templates_in_shell.html">How to Generate Files From Templates in
Shell</a><br>
+ <i>This replaced an old post from 2020 about the same topic.</i><br>
<time>2023-03-26</time>
<li> <a href="self_update_march_2023.html">Self Update: March 2023</a><br>
<time>2023-03-23</time>
@@ -95,9 +99,6 @@ software and hardware engineering. I post here my projects, experiments, and wha
<time>2020-05-29</time>
<li> <a href="half_of_my_css_are_links.html">Half of My CSS Are Links</a><br>
<time>2020-05-19</time>
-<li> <a href="the_gentlest_introduction_to_building_with_makefiles.html">The Gentlest Introduction to Building With
- Makefiles</a><br>
- <time>2020-05-14</time>
<li> <a href="markdown_is_bad_for_you.html">Markdown Is Bad for You</a><br>
<time>2020-05-13</time>
</ul>
diff --git a/the_gentlest_introduction_to_building_with_makefiles.html b/the_gentlest_introduction_to_building_with_makefiles.html
deleted file mode 100644
index 8bba6fa..0000000
--- a/the_gentlest_introduction_to_building_with_makefiles.html
+++ /dev/null
@@ -1,239 +0,0 @@
-<!doctype html>
-<html lang="en">
-<meta charset="utf-8">
-<meta name="viewport" content="width=device-width, initial-scale=1">
-<meta name="author" content="aki">
-<meta name="tags" content="tutorial, gnu make, makefile, compiling, building, C, C++">
-<link rel="icon" type="image/png" href="favicon.png">
-<link rel="stylesheet" type="text/css" href="style.css">
-
-<title>The Gentlest Introduction to Building With Makefiles</title>
-
-<nav><p><a href="https://ignore.pl">ignore.pl</a></p></nav>
-
-<article>
-<h1>The Gentlest Introduction to Building With Makefiles</h1>
-<p class="subtitle">Published on 2020-05-14 18:44:00+02:00
-<p>If you are here, you are most likely in need to build C or C++ program. Chances are you were not even looking for
-tutorial about <a href="https://www.gnu.org/software/make/">GNU make</a> or Makefiles in general. Chances are that you
-need to get you assignment done by yesterday, or you want to refresh your memory from back in the day you used C for
-the last time. No matter your background, I'll try to walk you through the process of building your C or C++ program
-using make command.
-<p>Sadly, the tutorial will explain the stuff, so that you have an overview after reading it. It won't go too deeply.
-Anyway, if you are only interested in an example to copy, there is one <a href="#example">below</a>.
-<p>If you have no idea, why using build system is nice. There are plenty of reasons. I will give you two. They automate
-the building process, so that you don't have to type same things all over again, and you don't need to remember your
-configuration at all times. If used consistently, they try to build only parts of your project that were changed. It
-can affect the building time greatly.
-<h2 id="single_file">Building a single file project</h2>
-<p>You have just finished writing your first implementation of <i>Hello, world!</i>, you have terminal open or some kind
-of prompt up and running, and now you would like to build the program and execute it. You've probably seen it somewhere
-but let me remind how to do it by hand using gcc:</p>
-<pre>
-$ ls
-hello.c
-$ gcc hello.c -o hello
-$ ./hello
-Hello, world!
-</pre>
-<p>Nice! But writing <code>gcc hello.c -o hello</code> all the time when you want to rebuild the program sounds
-bothersome even if you consider using command history. If you were to extend the program with libraries or additional
-files it sounds even more tiresome.
-<p>Let's put <i>make</i> to use! All you need to do is replace <code>gcc hello.c -o</code> part with <code>make</code>,
-so that you have:</p>
-<pre>
-$ ls
-hello.c
-<mark>$ make hello</mark>
-cc hello.c -o hello
-$ ls
-hello hello.c
-$ ./hello
-Hello, world!
-</pre>
-<p>You probably noticed that <i>make</i> shamelessly prints out the command it used to build your program. How did it
-know? <i>Make</i> is a master of default variables, implicit rules, deduction, and hiding it's secrets from curious eyes
-of those who seek knowledge. Actually, no, <a href="https://www.gnu.org/software/make/manual/make.html">the
-documentation</a> is available for anyone in various forms. We'll not discuss it in detail, that wouldn't be gentle, so
-assume for now that <i>make</i> will know how to compile and link your C or C++ program. Rules that describe how
-<i>make</i> does that are called <strong>implicit rules</strong>. We'll use and affect them extensively.</p>
-<img src="the_gentlest_introduction_to_building_with_makefiles-1.png" alt="colorful toy blocks">
-<h2 id="libraries">Using libraries with implicit rules</h2>
-<p><i>Make</i> and makefiles heavily rely on your environment. If you don't know what it is, for simplicity let's say
-that the environment is a set of variables associated with your current shell/terminal/prompt session. <i>Make</i> is
-so greedy that it takes all of your environmental variables and copies them as own. The implicit rules may use those
-copied variables, and they do exactly that. Those variables are usually called <strong>implicit variables</strong>.
-<p>We can take advantage of it. Let's say we are building a game with <a href="https://www.libsdl.org/">SDL2</a>. SDL2
-requires an additional include directory, a flag, and a library in order to build with it. Firstly, we'll set selected
-variables in our environment (via <code>export VARIABLE=value</code>), and then we'll build the program:</p>
-<pre>
-$ ls
-hello-sdl.c
-$ export <mark>CFLAGS</mark>='-D_REENTRANT -I/usr/include/SDL2'
-$ export <mark>LDLIBS</mark>='-lSDL2'
-$ make hello-sdl
-gcc <mark>-D_REENTRANT -I/usr/include/SDL2</mark> hello-sdl.c <mark>-lSDL2</mark> -o hello-sdl
-$ ./hello-sdl
-</pre>
-<p>The values I've used are specific to SDL2, don't mind them. What interests us in this example are the names of the
-variables: <code>CFLAGS</code> and <code>LDLIBS</code>. First one, is a set of parameters that describe how our thing
-should be handled during compilation. <code><strong>C</strong>FLAGS</code> is for C language, for C++ programs there is
-an equivalent variable called <code>CXXFLAGS</code>. Second variable, <code>LDLIBS</code> may contain a list of
-libraries that the linker should link to our program. In the example above there is no clear difference between
-compilation and linking, and thus both variables are copied by <i>make</i> to a single command. Luckily, it makes no
-difference to us, especially when the outcome is satisfying.
-<h2 id="first_makefile">First Makefile</h2>
-<p>Obviously, we would need to repeat those <code>exports</code> each time we start new session. This would bring us
-back to the level of repeating whole <code>gcc</code> call on and on. We could put them in some kind of file, couldn't
-we? Luckily, <i>make</i> predicted that and it may read the contents of so-called makefiles. Just put a file called
-<i>Makefile</i> in the project directory and insert the variables there:</p>
-<pre>
-CFLAGS=<mark>-D_REENTRANT -I/usr/include/SDL2</mark>
-LDLIBS=<mark>-lSDL2</mark>
-</pre>
-<p>Now, if you run <i>make</i>, it will read the <i>Makefile</i> and use the variables that are defined in it:</p>
-<pre>
-$ ls
-hello-sdl.c Makefile
-$ make hello-sdl
-gcc <mark>-D_REENTRANT -I/usr/include/SDL2</mark> hello-sdl.c <mark>-lSDL2</mark> -o hello-sdl
-</pre>
-<p>Less writing is always cool. How about getting rid of the <code>hello-sdl</code> from every call to <i>make</i>?
-That's also possible. <code>hello-sdl</code> is <strong>a target</strong>. Targets are associated with
-<strong>rules</strong>, any number of them, be it implicit or user-defined. If user doesn't provide a target name as an
-argument in command line, <i>make</i> uses first target that is specified in the makefile. We can create targets by
-writing rules. The syntax to do so is rather straight forward and contains: names of targets, prerequisites needed, and
-a recipe which may be a single-line command or may span the eternity. Knowing all of that, we can write a very peculiar
-rule. Everything will be handled by an implicit rule, and we'll only give a hint to <i>make</i> which thing we want it
-to build by default:</p>
-<pre>
-CFLAGS=-D_REENTRANT -I/usr/include/SDL2
-LDLIBS=-lSDL2
-<mark>hello-sdl:</mark>
-</pre>
-<p>Surprisingly, that's enough. <code>hello-sdl</code> is the name of our target. It's a first target that appears in
-this makefile, therefore it will be the default one. <code>:</code> (colon) is a required separator between the target
-and prerequisites list. We didn't add any dependencies, as the sole dependency on <i>hello-sdl.c</i> file is
-acknowledged thanks to the implicit rule. And because we didn't write any recipe, the recipe from the implicit rule is
-used. When we use it, it looks like this:</p>
-<pre>
-$ ls
-hello-sdl.c Makefile
-$ make
-gcc -D_REENTRANT -I/usr/include/SDL2 hello-sdl.c -lSDL2 -o hello-sdl
-</pre>
-<h2 id="more_files">Adding more files</h2>
-<img src="the_gentlest_introduction_to_building_with_makefiles-2.png" alt="more files">
-<p>In a long run, it would be more useful to have more than one file in a project. <i>Make</i> also predicted that and
-allows users to build programs from multiple sources. Amazing, isn't it? Now is the moment we finally split up
-compilation from linking in a visible manner. Let's say we have a project with three files <i>hello.c</i>,
-<i>sum.h</i> and <i>sum.c</i>, their content is respectively:</p>
-<pre>
-#include &lt;stdio.h&gt;
-<mark>#include "sum.h"</mark>
-int main(int argc, char * argv[]) {
- printf("2 + 3 = %d", <mark>sum(2, 3)</mark>);
-}
-</pre>
-<pre>
-#pragma once
-int sum(int a, int b);
-</pre>
-<pre>
-int sum(int a, int b) {
- return a + b;
-}
-</pre>
-<p>The structure of this project is easily seen. <i>Hello.c</i> depend directly on <i>sum.h</i> due to the include, and
-it requires the <i>sum</i> function to be compiled and available when linking the final executable. First dependency is
-so stupidly easy to write, that you might be actually surprised about it: you just need to add <i>sum.h</i> file to
-prerequisites in the rule description. The other one, is slightly more interesting. We could just add <i>sum.c</i> to
-prerequisites, but we will die a horrible death after a while if we do that. Technically, it's not even the thing we're
-trying to accomplish, so <strong>don't do that</strong>.
-<p>Instead, let's use <i>.o</i> files that are products of compilation of a single source file. We can link them
-together with libraries to form an executable. We are finally clearly dividing our building process into compilation
-stage, and linking stage. Let's introduce two such files: <i>hello.o</i> and <i>sum.o</i>. They are build from their
-respective sources. This means we now have <strong>three</strong> files with compiled or linked code: <i>hello</i>,
-<i>hello.o</i> and <i>sum.o</i>. Latter doesn't depend on anything, so there is no need for us to write anything about
-it. <i>hello.o</i> depends on <i>sum.h</i> (again, due to already mentioned include). Despite the fact that we call the
-<i>sum()</i> function in it, it doesn't depend on <i>sum.o</i>. Why? Because it is just an intermediate file. It never
-executes anything. On the other hand, <i>hello</i> executes it, so it needs all of the intermediate <i>.o</i> files in
-its prerequisites list.
-<p>All in all, the <i>Makefile</i> will look like this:</p>
-<pre>
-hello: hello.o sum.o
-hello.o: sum.h
-</pre>
-<p>When we use it:</p>
-<pre>
-$ make
-cc -c -o hello.o hello.c
-cc -c -o sum.o sum.c
-cc hello.o sum.o -o hello
-$ ./hello
-2 + 3 = 5
-</pre>
-<p>Surprisingly, that's all you need to know. With that, you can build pretty much everything. With time and when you
-gain some additional knowledge you may want to write your makefiles more explicitly: things like <code>CC=gcc</code> to
-make sure that the correct compiler is used. Your own recipes for generating headers or targets that are not generating
-any files, but rather install the software or clean up the directory. Targets not associated with files are called
-<strong>.PHONY</strong> and sooner or later you will encounter them. Actually...
-<h2 id="clean">Clean up your project directory with make</h2>
-<p>For some reasons, you may want to remove all built executables and intermediate files, or any other garbage files
-that your workflow involves. In previous part, I've already noted that you can accomplish that using <i>.PHONY</i>
-targets. Such cleaning target is quite common and is usually called <code>clean</code>. Consider the following:</p>
-<pre>
-hello: hello.o sum.o
-hello.o: sum.h
-
-clean:
-<mark> $(RM) *.o hello</mark>
-
-.PHONY: clean
-</pre>
-<p>As it's not the default target, you must invoke it by name:</p>
-<pre>
-$ make <mark>clean</mark>
-rm -f *.o hello
-</pre>
-<p>The marked line is called the recipe. It describes what rule is supposed to do. Only one recipe per target is used,
-<i>make</i> discards previous recipes for the target if new one is defined, so only the bottom-most is effective.
-<code>$(RM)</code> is a default variable that is expected to describe the command that can be used to safely remove
-files no longer needed by the project. You've probably noticed that <code>.PHONY</code> exists as a target. We add
-<code>clean</code> to it's prerequisites list to let <i>make</i> know that <code>clean</code> is not expected to create
-a file called <i>clean</i>.</p>
-<img src="the_gentlest_introduction_to_building_with_makefiles-3.png" alt="sweeping dust">
-<h2 id="example">Example makefile for C++ project</h2>
-<p>Following makefile is used to build a simple C++ pager, program for opening and scrolling through a file in a
-command line interface. Please note, that by default <i>cc</i> is used as a linker. It means that, if we are building
-a C++ project, the standard C++ library will be missing. We can avoid it by writing own linking recipe, or by adding
-<code>-lstdc++</code> to libraries manually. Latter approach is used in the example.</p>
-<pre>
-CXXFLAGS=-std=c++17 -Wall -Wextra -Werror -O2
-LDLIBS=-lstdc++ -lncurses++
-
-pager: ansi.o content.o pager.o
-pager.o: ansi.h content.h
-
-clean:
- $(RM) pager *.o
-
-.PHONY: clean
-</pre>
-<h2 id="next">What's next</h2>
-<p>Obviously, that's not everything there is to <i>make</i>. In my opinion, this is all you need for regular usage in
-small to medium projects. From this point you can extend your knowledge. I would suggest to learn more about
-<a href="https://www.gnu.org/software/make/manual/html_node/Using-Variables.html">variables</a> and built-in
-<a href="https://www.gnu.org/software/make/manual/html_node/Functions.html">functions</a>. They will help you to create
-more extendible makefiles, and write less in general. In case you'll end up needing to write a proper recipe and more
-complicated rule - head to sections:
-<a href="https://www.gnu.org/software/make/manual/html_node/Recipes.html">writing recipes</a> or
-<a href="https://www.gnu.org/software/make/manual/html_node/Rules.html">writing rules</a>.
-<a href="https://www.gnu.org/software/make/manual/html_node/Automatic-Variables.html">The automatic variables</a> are
-an amazingly useful tool when writing your own rules. Actually, these three things are usually, the first to be
-mentioned by other tutorials about <i>make</i>. However, with approach presented in here, you should be able to avoid
-them for quite a long time. <strong>Be wary</strong> though - don't be ignorant. You've been showed the basic usage of
-<i>make</i> that is heavily dependent on implicit rules and hidden mechanics. You know that they exists and now it's
-turn for you to go out there, use them and slowly learn how they really work.
-</article>
-<script src="https://stats.ignore.pl/track.js"></script>