{"id":239,"date":"2012-09-05T01:00:00","date_gmt":"2012-09-04T23:00:00","guid":{"rendered":"https:\/\/www.fussylogic.co.uk\/blog\/?p=239"},"modified":"2012-10-08T17:52:36","modified_gmt":"2012-10-08T16:52:36","slug":"replacing-an-ide-with-makefiles-3","status":"publish","type":"post","link":"https:\/\/www.fussylogic.co.uk\/blog\/?p=239","title":{"rendered":"Replacing an IDE With Makefiles"},"content":{"rendered":"<p>Developers have been led down a path by graphical tools. The tools in question are the so-called IDEs (integrated development environments). They are a nice idea in theory: combine your editor, compiler and debugger into one graphical program so that the developer can edit away, pressing \u00e2\u20ac\u0153build\u00e2\u20ac\u009d when they feel like it and single step through the running program for debugging. I can\u00e2\u20ac\u2122t deny that there is a certain appeal to it, and for getting you started in programming, they can be very useful.<\/p>\n<p>The problem with them is that they make you stupid. A developer in my office wouldn\u00e2\u20ac\u2122t use a free compiler I suggested because it didn\u00e2\u20ac\u2122t have an IDE to go with it. Instead, he\u00e2\u20ac\u2122d rather pay the hundreds of pounds per version charge for a compiler that comes with a graphical interface. Not me; and hopefully not you by the end of this article. The correct way (I think) is to keep each of your tools separate, this is the programmers way anyway \u00e2\u20ac\u201c modular thinking. The key advantage is that you can then swap out particular components for different jobs without having to relearn everything from scratch.<\/p>\n<p>UNIX is designed using this same philosophy \u00e2\u20ac\u201c small, interchangeable, easily connected tools that do one job and do it well. Everything I write is going to be about working on a Linux platform. There are ways of getting a similar environment on Windows (<a href=\"http:\/\/www.mingw.org\/\">MSYS<\/a> and <a href=\"http:\/\/www.cygwin.com\/\">Cygwin<\/a>), but I\u00e2\u20ac\u2122ll talk about them another day.<\/p>\n<p>Here then are my chosen tools:<\/p>\n<ul>\n<li>Plain text editor: <code>vim<\/code>. Many people don\u00e2\u20ac\u2122t like <code>vim<\/code>, that\u00e2\u20ac\u2122s fine. The beauty of a modular system is that you can use whatever suits you; <a href=\"http:\/\/www.scintilla.org\/SciTE.html\"><code>SciTE<\/code><\/a> and <a href=\"http:\/\/notepad-plus-plus.org\/\"><code>notepad++<\/code><\/a> are nice on Windows, and <code>kate<\/code>, <code>emacs<\/code>, <code>vim<\/code>, <code>nedit<\/code>, <code>gedit<\/code>, and <a href=\"http:\/\/fosswire.com\/post\/2010\/07\/text-based-text-editors\/\">many more<\/a> are all good on UNIX. <code>vim<\/code> is <a href=\"http:\/\/www.vim.org\/download.php\">available for Windows<\/a> and UNIX so I get the same editor whatever I\u00e2\u20ac\u2122m working on.<\/li>\n<li>Build system: <a href=\"http:\/\/www.gnu.org\/software\/make\/manual\/make.html\"><code>make<\/code><\/a>. <code>make<\/code> is the glue that holds the whole show together, it\u00e2\u20ac\u2122s essentially a program that runs lots of different snippets of shell script from a file you supply. That description doesn\u00e2\u20ac\u2122t really do it justice, but hopefully you\u00e2\u20ac\u2122ll understand more later.<\/li>\n<li>Command line: <code>bash<\/code>. We want some way of starting the compilation or running the program. In an IDE, there\u00e2\u20ac\u2122s a button to push. We\u00e2\u20ac\u2122ll be using a terminal with a command line running on it.<\/li>\n<li>Compiler: whatever. Depends on the job, we\u00e2\u20ac\u2122ll keep things simple here and build a native program, so we\u00e2\u20ac\u2122ll stick to <code>gcc<\/code>. There is an advantage to choosing <code>gcc<\/code> as well in that it is widely cross-platform, there is a <code>gcc<\/code> compiler or cross-compiler for almost every system and CPU. The Windows version is called <code>mingw<\/code>.<\/li>\n<\/ul>\n<p>Let\u00e2\u20ac\u2122s begin then\u00e2\u20ac\u00a6 open up a terminal (possibly labelled xterm) and get yourself a command line to start issuing commands. I\u00e2\u20ac\u2122ll mainly be showing command line examples. I\u00e2\u20ac\u2122ll be writing them like this:<\/p>\n<pre><code># Comment about what name_of_command will do\n$ name_of_command command_line_parameters\nSample output of command.<\/code><\/pre>\n<p>You would type the bit after the \u00e2\u20ac\u0153<span class=\"math\">$&quot; and you&#8217;d expect to see something like the sample output when you do; I&#8217;ll write comments prefixed with a &quot;#&quot;, you shouldn&#8217;t enter these nor expect to see them in the output &#8212; I&#8217;ve added them only as explanation. You don&#8217;t type the &quot;$<\/span>\u00e2\u20ac\u009d, that\u00e2\u20ac\u2122s just there to show that this is a command prompt, and \u00e2\u20ac\u0153$\u00e2\u20ac\u009d is commonly the default character used already on your system.<\/p>\n<p>We\u00e2\u20ac\u2122ll want some tools to begin, so let\u00e2\u20ac\u2122s install them. On Debian:<\/p>\n<pre><code>$ sudo apt-get install g++ make manpages-dev<\/code><\/pre>\n<p>Or use whatever package management system you\u00e2\u20ac\u2122re comfortable with to get these programs. I\u00e2\u20ac\u2122m assuming that you already have a text editor that you\u00e2\u20ac\u2122re comfortable with. If not, now is the time to find one and get comfortable with it.<\/p>\n<p>Let\u00e2\u20ac\u2122s begin with the classic, \u00e2\u20ac\u0153Hello, World\u00e2\u20ac\u009d.<\/p>\n<pre><code># Change to our home directory, and make an empty directory\n# to work in\n$ cd\n$ mkdir -p projects\/hello\n$ cd project\/hello\n# Start the editor of your choice...\n$ vim hello.cc<\/code><\/pre>\n<p>Then enter the source for the C++ program:<\/p>\n<pre class=\"sourceCode C\"><code class=\"sourceCode c\"><span class=\"ot\">#include &lt;iostream&gt;<\/span>\nusing namespace std;\n\n<span class=\"dt\">int<\/span> main()\n{\n    cout &lt;&lt; <span class=\"st\">&quot;Hello, World!&quot;<\/span> &lt;&lt; endl;\n    <span class=\"kw\">return<\/span> <span class=\"dv\">0<\/span>;\n}<\/code><\/pre>\n<p>Now we\u00e2\u20ac\u2122ll compile that manually.<\/p>\n<pre><code>$ g++ -o hello hello.cc\n$ .\/hello\nHello, World!<\/code><\/pre>\n<p>Pretty simple? The C++ compiler, <code>g++<\/code> would default to outputting a program called <code>a.out<\/code> if we didn\u00e2\u20ac\u2122t override that with <code>-o hello<\/code>; and of course the <code>hello.cc<\/code> parameter simply tells it what source file to compile.<\/p>\n<p>This is okay, but the compiler command line is already tediously long to type, and it\u00e2\u20ac\u2122s near the shortest compiler command line we could have. Let\u00e2\u20ac\u2122s write a <code>Makefile<\/code> to take care of calling the compiler, and remembering the command line options we want for us. Put the following in the same directory with the name <code>Makefile<\/code> (the initial capital is important).<\/p>\n<pre class=\"sourceCode Makefile\"><code class=\"sourceCode makefile\"><span class=\"dv\">run:<\/span> hello\n    .\/hello\n\n<span class=\"dv\">hello:<\/span> hello.cc\n    g<span class=\"ch\">++<\/span> -o hello hello.cc<\/code><\/pre>\n<p>A <code>Makefile<\/code> is a list of so-called <code>recipes<\/code>. The form of a recipe is like this:<\/p>\n<pre class=\"sourceCode Makefile\"><code class=\"sourceCode makefile\"><span class=\"dv\">target:<\/span> dependency\n    commands_to_make_target_from_dependency<\/code><\/pre>\n<p>The indent before the command <em>must<\/em> be a real tab. Spaces won\u00e2\u20ac\u2122t work. So, you can see that our <code>hello<\/code> <code>Makefile<\/code> tells make that to create the file <code>hello<\/code> from the file <code>hello.cc<\/code> it should run <code>g++ -o hello hello.cc<\/code>. For convenience, I\u00e2\u20ac\u2122ve also included a <code>run<\/code> recipe. This tells make that to create <code>run<\/code> it needs a file called <code>hello<\/code>, and it should run <code>.\/hello<\/code>. The clever feature of <code>make<\/code> is that if, when it comes to execute the <code>run<\/code> recipe, it can\u00e2\u20ac\u2122t find a file called <code>hello<\/code>, it will look through it\u00e2\u20ac\u2122s other recipes and see if it has been told how to create it. We can check that like this:<\/p>\n<pre><code>$ rm -f hello\n$ make run\ng++ -o hello hello.cc\n.\/hello\nHello, World!<\/code><\/pre>\n<p>You can see that <code>make<\/code> first ran the compiler (it echoes the commands it\u00e2\u20ac\u2122s running to the screen), and <em>then<\/em> runs the program.<\/p>\n<p>Let\u00e2\u20ac\u2122s improve the <code>Makefile<\/code> a little.<\/p>\n<pre class=\"sourceCode Makefile\"><code class=\"sourceCode makefile\"><span class=\"dv\">run:<\/span> hello\n    .\/<span class=\"ch\">$<\/span>&lt;\n<span class=\"dv\">clean:<\/span>\n    <span class=\"ch\">-<\/span><span class=\"bn\">rm<\/span> -f hello\n\n<span class=\"dv\">hello:<\/span> hello.cc\n    g<span class=\"ch\">++<\/span> -o <span class=\"ch\">$<\/span>@ <span class=\"ch\">$<\/span>&lt;<\/code><\/pre>\n<p>The compiler recipe has changed to <code>g++ -o $@ $&lt;<\/code>, this looks a little like a cat has walked on the keyboard, but really it is making use of <code>make<\/code>\u00e2\u20ac\u2122s variable facility. Variables in make are prefixed with a \u00e2\u20ac\u0153$\u00e2\u20ac\u009d.<\/p>\n<ul>\n<li>the \u00e2\u20ac\u0153<code>$@<\/code>\u00e2\u20ac\u009d variable means <em>the name given as the target of this recipe<\/em>.<\/li>\n<li>the \u00e2\u20ac\u0153<code>$&lt;<\/code>\u00e2\u20ac\u009d variable means <em>the first dependency in the given list<\/em>.<\/li>\n<\/ul>\n<p>In short, it means we don\u00e2\u20ac\u2122t have to write <code>hello<\/code> and <code>hello.cc<\/code> again \u00e2\u20ac\u201c the fact that we named them in the recipe declaration means that <code>make<\/code> already knows what they are. Why do we want to do this? We\u00e2\u20ac\u2122ll see more later, but for now just notice that if we renamed <code>hello.cc<\/code> to <code>helloworld.cc<\/code> we would only have one place to change in the <code>Makefile<\/code>.<\/p>\n<p>We\u00e2\u20ac\u2122ve also used this facility to make the <code>run<\/code> recipe run whatever dependency it is given, in our case <code>hello<\/code>. Again, we\u00e2\u20ac\u2122ve reduced the number of places that we have to state a name.<\/p>\n<p>There is now also a <code>clean<\/code> recipe, which runs the deletion command we showed earlier. This means we don\u00e2\u20ac\u2122t have to worry about mistyping when we\u00e2\u20ac\u2122re deleting and leaves us with an easy way to go back to a directory with no compiler output in it.<\/p>\n<p>There\u00e2\u20ac\u2122s more we can do yet to improve our <code>Makefile<\/code>, the compile recipe can be changed to:<\/p>\n<pre class=\"sourceCode Makefile\"><code class=\"sourceCode makefile\"><span class=\"ch\">%:<\/span> <span class=\"ch\">%<\/span>.cc\n    g<span class=\"ch\">++<\/span> -o <span class=\"ch\">$<\/span>@ <span class=\"ch\">$<\/span>&lt;<\/code><\/pre>\n<p>Let\u00e2\u20ac\u2122s see what happens when we run it:<\/p>\n<pre><code>$ make clean\nrm -f hello\n$ make run\ng++ -o hello hello.cc\n.\/hello\nHello, World!<\/code><\/pre>\n<p>What\u00e2\u20ac\u2122s this? Exactly the same as before. We changed our compiler recipe definition from \u00e2\u20ac\u0153<code>hello: hello.cc<\/code>\u00e2\u20ac\u009d to \u00e2\u20ac\u0153<code>%: %.cc<\/code>\u00e2\u20ac\u009d. This is a pattern recipe. We\u00e2\u20ac\u2122re telling <code>make<\/code> that it can create a file called <code>XYZ<\/code> by compiling <code>XYZ.cc<\/code>, and that this works for any <code>XYZ<\/code>. We represent that \u00e2\u20ac\u0153any\u00e2\u20ac\u009d with the <code>%<\/code> symbol. Now, when we run <code>make<\/code>, it decides that to create the <code>run<\/code> target, it needs the file <code>hello<\/code>, but there is no <code>hello<\/code> file, it checks its recipes and finds that it knows how to create <code>hello<\/code> if it has <code>hello.cc<\/code> (\u00e2\u20ac\u0153<code>%: %.cc<\/code>\u00e2\u20ac\u009d). It <em>does<\/em> have <code>hello.cc<\/code> available, so it runs that pattern recipe, expanding the \u00e2\u20ac\u0153%\u00e2\u20ac\u009d symbol appropriately. We see now the additional advantage to our use of \u00e2\u20ac\u0153<code>$@<\/code>\u00e2\u20ac\u009d and \u00e2\u20ac\u0153<code>$&lt;<\/code>\u00e2\u20ac\u009d for specifying the files to the compiler \u00e2\u20ac\u201c they take on the values of the target and dependency <em>after<\/em> the expansion of \u00e2\u20ac\u0153%\u00e2\u20ac\u009d. So, make turns \u00e2\u20ac\u0153<code>%: %.cc<\/code>\u00e2\u20ac\u009d into \u00e2\u20ac\u0153<code>hello: hello.cc<\/code>\u00e2\u20ac\u009d, and then uses that to turn \u00e2\u20ac\u0153<code>g++ -o $@ $&lt;<\/code>\u00e2\u20ac\u009d into \u00e2\u20ac\u0153<code>g++ -o hello hello.cc<\/code>\u00e2\u20ac\u009d; which is exactly what it runs.<\/p>\n<p>There is more to be done yet. Let\u00e2\u20ac\u2122s get the names of things written as few times as we can, and lets split the compile command into more flexible separate compile and link stages.<\/p>\n<pre class=\"sourceCode Makefile\"><code class=\"sourceCode makefile\"><span class=\"dt\">NAME <\/span><span class=\"st\">:= hello<\/span>\n\n<span class=\"dv\">run:<\/span> <span class=\"ch\">$(<\/span><span class=\"dt\">NAME<\/span><span class=\"ch\">)<\/span>\n    .\/<span class=\"ch\">$<\/span>&lt;\n<span class=\"dv\">clean:<\/span>\n    <span class=\"ch\">-<\/span><span class=\"bn\">rm<\/span> -f <span class=\"ch\">$(<\/span><span class=\"dt\">NAME<\/span><span class=\"ch\">)<\/span>\n    <span class=\"ch\">-<\/span><span class=\"bn\">rm<\/span> -f <span class=\"ch\">$(<\/span><span class=\"dt\">NAME<\/span><span class=\"ch\">)<\/span>.o\n\n<span class=\"ch\">%<\/span>.o<span class=\"ch\">:<\/span> <span class=\"ch\">%<\/span>.cc\n    g<span class=\"ch\">++<\/span> -c <span class=\"ch\">$<\/span>&lt;\n<span class=\"ch\">%:<\/span> <span class=\"ch\">%<\/span>.o\n    g<span class=\"ch\">++<\/span> -o <span class=\"ch\">$<\/span>@ <span class=\"ch\">$<\/span>&lt;<\/code><\/pre>\n<p>What we\u00e2\u20ac\u2122ve done here is make a user variable called <code>NAME<\/code> to hold the word <code>hello<\/code>. User variables are just like the <code>$@<\/code> and <code>$&lt;<\/code> we saw earlier, but they are not assigned automatically, we must assign them something. The first line is that assignment. Then, whenever we need to use <code>hello<\/code>, we write <code>$(NAME)<\/code> instead and rely on <code>make<\/code> to substitute <code>hello<\/code> in when it is running. In this way we\u00e2\u20ac\u2122ve removed all but one of the explicit uses of a filename. You can imagine that should we want to start a new project, it would be very easy to copy this <code>Makefile<\/code> and change the <code>NAME<\/code> at the top as appropriate.<\/p>\n<p>We can also use variables to hold settings for the whole file \u00e2\u20ac\u201c for example switches to the compiler and linker. By keeping all the settings in one place near the top, we make it easier to customise the build without getting bogged down in the actual command lines.<\/p>\n<p>This <code>Makefile<\/code> is still a little limited because it only compiles one source file. When a project gets larger, we want to be able to compile multiple source files into their respective object files, then link all into one final executable. Let\u00e2\u20ac\u2122s alter our <code>Makefile<\/code> to do that automatically for a directory filled with source files.<\/p>\n<pre class=\"sourceCode Makefile\"><code class=\"sourceCode makefile\"><span class=\"dt\">TARGET <\/span><span class=\"st\">:= hello<\/span>\n\n<span class=\"dt\">SOURCE <\/span><span class=\"st\">:= <\/span><span class=\"ch\">$(<\/span><span class=\"dt\">wildcard *.cc<\/span><span class=\"ch\">)<\/span>\n<span class=\"dt\">OBJS   <\/span><span class=\"st\">:= <\/span><span class=\"ch\">$(<\/span><span class=\"dt\">SOURCE:.cc=.o<\/span><span class=\"ch\">)<\/span>\n\n<span class=\"dv\">run:<\/span> <span class=\"ch\">$(<\/span><span class=\"dt\">TARGET<\/span><span class=\"ch\">)<\/span>\n    .\/<span class=\"ch\">$<\/span>&lt;\n<span class=\"dv\">clean:<\/span>\n    <span class=\"ch\">-<\/span><span class=\"bn\">rm<\/span> -f <span class=\"ch\">$(<\/span><span class=\"dt\">TARGET<\/span><span class=\"ch\">)<\/span>\n    <span class=\"ch\">-<\/span><span class=\"bn\">rm<\/span> -f <span class=\"ch\">$(<\/span><span class=\"dt\">OBJS<\/span><span class=\"ch\">)<\/span>\n\n<span class=\"ch\">$(<\/span><span class=\"dt\">TARGET<\/span><span class=\"ch\">):<\/span> <span class=\"ch\">$(<\/span><span class=\"dt\">OBJS<\/span><span class=\"ch\">)<\/span>\n    g<span class=\"ch\">++<\/span> -o <span class=\"ch\">$<\/span>@ <span class=\"ch\">$<\/span>^\n<span class=\"ch\">%<\/span>.o<span class=\"ch\">:<\/span> <span class=\"ch\">%<\/span>.cc\n    g<span class=\"ch\">++<\/span> -c <span class=\"ch\">$<\/span>&lt;<\/code><\/pre>\n<p>There are two key features of <code>make<\/code> we\u00e2\u20ac\u2122ve used here:<\/p>\n<ul>\n<li>Function expansions. <code>$(wildcard)<\/code> is a special variable which, rather than expand to a value that was set earlier, instead performs an operation to generate the value. For <code>$(wildcard *.cc)<\/code> it looks in the current directory for all the files that end with \u00e2\u20ac\u0153<code>.cc<\/code>\u00e2\u20ac\u009d. That list is then written to the user variable, SOURCE.<\/li>\n<li>Pattern substitution. We know that <code>$(SOURCE)<\/code> would be replaced with the value of the <code>SOURCE<\/code> variable. However, <code>make<\/code> gives an additional syntax which lets us run a pattern substitution on the replacement. That mode is activated by ending the variable name with a colon, \u00e2\u20ac\u0153:\u00e2\u20ac\u009d. For example, <code>$(SOURCE:.cc=.o)<\/code> looks up the variable <code>SOURCE<\/code>, and then converts every instance of \u00e2\u20ac\u0153<code>.cc<\/code>\u00e2\u20ac\u009d within it into \u00e2\u20ac\u0153<code>.o<\/code>\u00e2\u20ac\u009d. (See also the <code>patsubst<\/code> function in the <a href=\"http:\/\/www.gnu.org\/software\/make\/manual\/make.html\"><code>make<\/code><\/a> documentation)<\/li>\n<\/ul>\n<p>Then we use features we\u00e2\u20ac\u2122ve already seen. We say that to make <code>$(TARGET)<\/code> requires all the files listed in $(OBJS), for each of which we already have a pattern recipe to make the \u00e2\u20ac\u0153<code>.o<\/code>\u00e2\u20ac\u009d from the \u00e2\u20ac\u0153<code>.cc<\/code>\u00e2\u20ac\u009d source.<\/p>\n<p>One final change. We\u00e2\u20ac\u2122ve got recipes for \u00e2\u20ac\u0153run\u00e2\u20ac\u009d and \u00e2\u20ac\u0153clean\u00e2\u20ac\u009d, and <code>make<\/code> treats these as filenames. Of course these files will never be made as the recipes we supply for these targets don\u00e2\u20ac\u2122t create any files. That means we can run \u00e2\u20ac\u0153<code>make run<\/code>\u00e2\u20ac\u009d as many times as we wish \u00e2\u20ac\u201c it will <em>always<\/em> run. However, if there were a file called \u00e2\u20ac\u0153run\u00e2\u20ac\u009d in the directory, the recipe would <em>never<\/em> run since the target would already exist. To avoid this sort of thing biting us in the future, we can tell <code>make<\/code> that these aren\u00e2\u20ac\u2122t to be treated as filenames, that it should always run them. While we\u00e2\u20ac\u2122re doing that, we\u00e2\u20ac\u2122ll add a separate \u00e2\u20ac\u0153build\u00e2\u20ac\u009d recipe, making it optional to run the final executable.<\/p>\n<pre class=\"sourceCode Makefile\"><code class=\"sourceCode makefile\"><span class=\"dt\">TARGET <\/span><span class=\"st\">:= hello<\/span>\n<span class=\"dt\">CCFLAGS <\/span><span class=\"st\">:= -O2 -g -Wall<\/span>\n<span class=\"dt\">LDFLAGS <\/span><span class=\"st\">:= -static<\/span>\n\n<span class=\"dt\">SOURCE <\/span><span class=\"st\">:= <\/span><span class=\"ch\">$(<\/span><span class=\"dt\">wildcard *.cc<\/span><span class=\"ch\">)<\/span>\n<span class=\"dt\">OBJS   <\/span><span class=\"st\">:= <\/span><span class=\"ch\">$(<\/span><span class=\"dt\">SOURCE:.cc=.o<\/span><span class=\"ch\">)<\/span>\n\n<span class=\"dv\">default:<\/span> build\n<span class=\"dv\">build:<\/span> <span class=\"ch\">$(<\/span><span class=\"dt\">TARGET<\/span><span class=\"ch\">)<\/span>\n<span class=\"dv\">run:<\/span> build\n    .\/<span class=\"ch\">$<\/span>&lt;\n<span class=\"dv\">clean:<\/span>\n    <span class=\"ch\">-<\/span><span class=\"bn\">rm<\/span> -f <span class=\"ch\">$(<\/span><span class=\"dt\">TARGET<\/span><span class=\"ch\">)<\/span>\n    <span class=\"ch\">-<\/span><span class=\"bn\">rm<\/span> -f <span class=\"ch\">$(<\/span><span class=\"dt\">OBJS<\/span><span class=\"ch\">)<\/span>\n\n<span class=\"ch\">$(<\/span><span class=\"dt\">TARGET<\/span><span class=\"ch\">):<\/span> <span class=\"ch\">$(<\/span><span class=\"dt\">OBJS<\/span><span class=\"ch\">)<\/span>\n    g<span class=\"ch\">++<\/span> <span class=\"ch\">$(<\/span><span class=\"dt\">LDFLAGS<\/span><span class=\"ch\">)<\/span> -o <span class=\"ch\">$<\/span>@ <span class=\"ch\">$<\/span>^\n<span class=\"ch\">%<\/span>.o<span class=\"ch\">:<\/span> <span class=\"ch\">%<\/span>.cc\n    g<span class=\"ch\">++<\/span> <span class=\"ch\">$(<\/span><span class=\"dt\">CCFLAGS<\/span><span class=\"ch\">)<\/span> -c <span class=\"ch\">$<\/span>&lt;\n\n<span class=\"ot\">.PHONY:<\/span> default build run clean<\/code><\/pre>\n<p>We\u00e2\u20ac\u2122ve only touched the surface of <code>make<\/code> here, but this is a good start, and enough of an example that it would work in real projects.<\/p>\n<p>More importantly though is to compare this with what an IDE would have provided us. The working directory would be full of unreadable, non-standard configuration files, with no guarantee that an upgrade of the IDE would leave them operational. These would represent the options set in the GUI. We would have to remember which compile options we changed from the default, with no easy way to see which those were and no guarantee that they don\u00e2\u20ac\u2122t change with an upgrade. The options would have been set in page after page of dialog boxes, with generally poor organisation; mixing commonly-used settings with esoteric and complicated settings that we wouldn\u00e2\u20ac\u2122t ever have call to change. Our <code>Makefile<\/code> on the other hand records our settings for the build like this:<\/p>\n<pre class=\"sourceCode Makefile\"><code class=\"sourceCode makefile\"><span class=\"dt\">TARGET <\/span><span class=\"st\">:= hello<\/span>\n<span class=\"dt\">CCFLAGS <\/span><span class=\"st\">:= -O2 -g -Wall<\/span>\n<span class=\"dt\">LDFLAGS <\/span><span class=\"st\">:= -static<\/span><\/code><\/pre>\n<p>The use of functional expansions in the <code>Makefile<\/code> means that should we add more source files to the project, we won\u00e2\u20ac\u2122t have to change the Makefile at all. The fact that we can add utility recipes (like \u00e2\u20ac\u0153<code>clean<\/code>\u00e2\u20ac\u009d) means that we can tailor our <code>Makefile<\/code> to do useful things for the specific project we\u00e2\u20ac\u2122re working on. The <code>Makefile<\/code> is simple, when something goes wrong we can easily find out which part was responsible for the broken operation, and can easily make a change to fix it. In an IDE, we have no idea exactly what it did when we said \u00e2\u20ac\u0153build\u00e2\u20ac\u009d and we have no idea which dialog box to go to to change when something goes wrong.<\/p>\n<p>The price for all this is that it\u00e2\u20ac\u2122s slightly harder to get started with <code>make<\/code> than it is with an IDE, there is no plug-and-play facility with <code>make<\/code> and a command-line. You need to be given help to get you started \u00e2\u20ac\u201c the above was your help.<\/p>\n<p>As with almost everything in UNIX, it\u00e2\u20ac\u2122s harder to learn but easier to use.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Developers have been led down a path by graphical tools. The tools in question are the so-called IDEs (integrated development environments). They are a nice idea in theory: combine your editor, compiler and debugger into one graphical program so that the developer can edit away, pressing \u00e2\u20ac\u0153build\u00e2\u20ac\u009d when they feel like it and single step\u2026 <span class=\"read-more\"><a href=\"https:\/\/www.fussylogic.co.uk\/blog\/?p=239\">Read More &raquo;<\/a><\/span><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[1],"tags":[6],"_links":{"self":[{"href":"https:\/\/www.fussylogic.co.uk\/blog\/index.php?rest_route=\/wp\/v2\/posts\/239"}],"collection":[{"href":"https:\/\/www.fussylogic.co.uk\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.fussylogic.co.uk\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.fussylogic.co.uk\/blog\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.fussylogic.co.uk\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=239"}],"version-history":[{"count":8,"href":"https:\/\/www.fussylogic.co.uk\/blog\/index.php?rest_route=\/wp\/v2\/posts\/239\/revisions"}],"predecessor-version":[{"id":805,"href":"https:\/\/www.fussylogic.co.uk\/blog\/index.php?rest_route=\/wp\/v2\/posts\/239\/revisions\/805"}],"wp:attachment":[{"href":"https:\/\/www.fussylogic.co.uk\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=239"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.fussylogic.co.uk\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=239"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.fussylogic.co.uk\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=239"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}