<?xml version="1.0" encoding="ISO-8859-1"?><html xmlns="http://www.w3.org/1999/xhtml" xmlns:xh="http://www.w3.org/1999/xhtml" xmlns:axle="http://www.cs.odu.edu/~zeil/axle" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:ns0="http://www.cs.odu.edu/~zeil/axle" mode="ignore" id="make" ns0:xlinkuri="open/make.dbk" ns0:xpath="//*[@id='make']" ns0:page="make" foo="0 " ns0:last="/cocoon/~cs252/open/make/section-5.html"><head><title>Project Management with Make</title><link type="text/css" href="_axle/docbookstyle.css" rel="stylesheet"/><link type="text/css" href="_axle/cppformat.css" rel="stylesheet"/><link type="text/css" href="_axle/overrides.css" rel="stylesheet"/><script src="_axle/docbook.js"/><link href="http://cocoon.cs.odu.edu:80/cocoon/~cs252/open/make/section-1.html" title="Next" rel="next"/><link href="http://cocoon.cs.odu.edu:80/cocoon/~cs252/open/make/section-5.html" title="Last" rel="last"/><script>function gotoNext() {top.location.href="/cocoon/~cs252/open/make/section-1.html";}
function gotoPrev() {}
function gotoUp() {}
</script><xhtml:link xmlns:xhtml="http://www.w3.org/1999/xhtml" rel="stylesheet" href="_axle/navigation.css" type="text/css"/><xhtml:script xmlns:xhtml="http://www.w3.org/1999/xhtml" src="_axle/navigation.js"/></head><body><table width="100%" class="navigationBar"><tr class="navigationBar"><td width="5%" class="navigationBar"><a class="navigationBarArrow" title="Next" href="http://cocoon.cs.odu.edu:80/cocoon/~cs252/open/make/section-1.html"><img class="navigationBar" src="_axle/next.gif" alt="Next"/></a></td><td width="5%" class="navigationBar"><a class="navigationBarArrow" title="Last" href="http://cocoon.cs.odu.edu:80/cocoon/~cs252/open/make/section-5.html"><img class="navigationBar" src="_axle/last.gif" alt="Last"/></a></td><td class="navigationBar"/><td width="5%" class="navigationBar"><a class="navigationBar" title="CS252 Home" href="http://cocoon.cs.odu.edu:80/cocoon/~cs252/directory/announcements.html"><img class="navigationBar" src="_axle/home.gif" alt="CS252 Home"/></a></td><td width="5%" class="navigationBar"><a class="navigationBar" title="discuss this page" href="http://cocoon.cs.odu.edu:80/cocoon/~cs252/forum/getXPath/open/make/make.html"><img class="navigationBar" src="_axle/forum.gif" alt="discuss this page"/></a></td></tr></table><br/><div class="info_article"><div class="title_article">Project Management with Make</div><div class="author_article"><span class="firstname">Steven</span> <span class="othername" role="mi">J</span> <span class="surname">Zeil</span></div><div class="affiliation">
        <span class="orgname">Old Dominion University</span>
        <span class="orgdiv">Dept. of Computer Science</span>
      </div><table width="100%"><tr><td align="left"><span class="copyright">©<span class="year">2000-2006</span> <span class="holder">Steven J. Zeil, Old Dominion University</span></span></td><td/><td align="right"><span class="date">Jul. 16, 2005</span></td></tr></table></div><div class="TOC">Contents:<div class="TOC-section0"><a href="section-1.html#section-1">1 Symbols</a></div><div class="TOC-section0"><a href="section-2.html#section-2">2 Default Rules</a></div><div class="TOC-section0"><a href="artificial-targets.html#artificial-targets">3 Common Conventions</a></div><div class="TOC-section0"><a href="writingMakefiles.html#writingMakefiles">4 Creating a Makefile</a></div><div class="TOC-section0"><a href="section-5.html#section-5">5 Is It Worth It?</a></div></div>
  
  <div class="epigraph">
    <p class="para" align="center">
              (A printable version of this document is available 
              <a url="allPages.html" href="allPages.html">here</a>.)
            </p>
  </div>
  <p class="para">When you begin to develop projects that involve multiple files that
need to be compiled or otherwise processed, keeping them all
up-to-date can be a problem. Even more of a problem is passing them on
to someone else (e.g., your instructor) and expecting them to know
what to do to build your project from the source code.</p>
  <p class="para">The Unix program <span class="code">make</span> is designed to simplify such project
management. In a <span class="emphasis">makefile</span>, you record the steps necessary to
build both the final file (e.g., your executable program) and each
intermediate file (e.g., the <span class="code">.o</span> files produced by compiling a
single source code file).</p>
  <p class="para">We say that a file <span class="code">file1</span> <span class="emphasis">depends upon</span> a second file <span class="code">file2</span> if the <span class="code">file2</span> is used
as input to some command used to produce <span class="code">file1</span>.</p>
  <p class="para">When the <span class="code">make</span> program is run, it then
checks to be sure that all of the needed files exist, and that each
needed file has been updated more recently than all of the files it
depends upon. The key bits of information in a makefile, therefore are
<div class="itemizedlist"><ul><li>For each file, a list of other files it depends upon, and</li><li>The command used to produce the dependent file from the files it
depends upon.</li></ul></div>
A makefile may also include various macros/abbreviations designed to
simplify the task of dealing with many instances of the same commands
or files.</p>
  <p class="para">Suppose that we are engaged in a project to produce 2 programs,
<span class="code">progA</span> and <span class="code">progB</span>. <span class="code">progA</span> is produced by compiling
files <span class="code">utilities.c</span>, <span class="code">progA1.cpp</span>, and <span class="code">progA2.cpp</span> and
linking together the resulting <span class="code">.o</span> files. Program <span class="code">progB</span>
is produced by compiling file <span class="code">utilities.c</span> and <span class="code">progB1.cpp</span>
and linking together the resulting <span class="code">.o</span> files.  All of the
<span class="code">.c</span> and <span class="code">.cpp</span> files have <span class="code">#include</span> statements for a file
<span class="code">utilities.h</span>. Also, both of the <span class="code">.cpp</span> files have an
<span class="code">#include</span> statement for a file <span class="code">progA1.h</span>.</p>
  <p class="para">Here is a
makefile for this project.  This file should reside in the project
directory, and should be called <span class="quote">
      &#8220;<span class="code">Makefile</span>&#8221;
    </span> or
<span class="quote">
      &#8220;<span class="code">makefile</span>&#8221;
    </span>.</p>
  <p class="para">
    <div class="programlisting">
progA: utilities.o progA1.o progA2.o
        g++ -g -DDEBUG utilities.o progA1.o progA2.o
        mv a.out progA
  
progB: utilities.o progB1.o
        g++ -g -DDEBUG utilities.o progB1.o
        mv a.out progB
  
utilities.o: utilities.c utilities.h
        g++ -g -DDEBUG -c utilities.c
  
progA1.o: progA1.cpp utilities.h progA1.h
        g++ -g -DDEBUG -c progA1.cpp
  
progA2.o: progA2.cpp utilities.h progA1.h
        g++ -g -DDEBUG -c progA2.cpp
  
progB1.o: progB1.cpp
        g++ -g -DDEBUG -c progB1.cpp
</div>
  </p>
  <p class="para">The key information in a makefile consists of a variety of rules for
producing <span class="quote">
      &#8220;target&#8221;
    </span> files.
Each target rule 
begins with a single line containing the name of the file to produce,
a colon, and then a list of all files that serve as inputs to the
commands that produce the file. Following that are any number of
command lines that give the Unix commands to actually produce the
file. Each command line starts with a <span class="quote">
      &#8220;Tab&#8221;
    </span> character (invisible in
this listing).<a onmouseover="DBshowBriefly('fn_fref1_live')" name="fn_fref1" id="fn_fref1" class="footnotemark" href="section-5.html#fn_fnote1">1</a><div class="footnote_live" id="fn_fref1_live">A common mistake in preparing makefiles is to
use ordinary spaces instead of a tab character in front of these
command lines. The usual result of this mistake is the error message
<div class="programlisting">
  Makefile:N *** missing separator
</div> 
where N is the approximate line number where the error occurs. The
"separator" here refers to the fact tha <span class="code">make</span> expects each
rule to be separated from the others by one or more empty lines. A
line that starts with a space (instead of a tab) is assumed to be a
new rule. Since command lines are not separated from the rest of the
rule, a command line  starting with a blank
instead of a tab appears to <span class="code">make</span> as a new rule starting
up without an empty line separating it from the previous rule.</div>
</p>
  <p class="para">Suppose that, with just this <span class="code">Makefile</span> and the various source
code files in your directory, you issued the command
<div class="screen"><span class="userinput">make progB</span>
</div>
<span class="code">make</span> reads the <span class="code">Makefile</span> and notes
that <span class="code">progB</span> depends upon <span class="code">utilities.o</span> and <span class="code">progB1.o</span>.
Since neither of these files exists, <span class="code">make</span> sets out to create
them. <span class="code">utilities.o</span> depends upon <span class="code">utilities.c</span> and
<span class="code">utilities.h</span>. Since these files exist and do not themselves
depend upon anything else, <span class="code">make</span> will issue the command to
create <span class="code">utilities.o</span> from them. This command is the <span class="quote">
      &#8220;standard&#8221;
    </span>
command for making a <span class="code">.o</span> file from a <span class="code">.c</span> file:
<div class="screen"><span class="userinput">   gcc -g -DDEBUG -c utilities.c
</span></div>
Next <span class="code">make</span> looks at <span class="code">progB1.o</span>. It depends upon
<span class="code">progB1.cpp</span> which exists and does not depend upon anything else.
So <span class="code">make</span> uses the standard command for <span class="code">C++</span> files:
<div class="programlisting">
   g++ -g -DDEBUG -c progB1.cpp
</div>
Now that both <span class="code">.o</span> files have been created, <span class="code">make</span> proceeds
to build its main target, <span class="code">progB</span>, using the command lines
provided for that purpose:
<div class="programlisting">
   g++ -g -DDEBUG utilities.o progB1.o
</div>
and the <span class="code">progB</span> program has been created.</p>
  <p class="para">Now suppose that we immediately give the command 
<div class="screen"><span class="userinput">make progA</span>
</div>
(or
just <span class="quote">
      &#8220;<span class="userinput">make</span>&#8221;
    </span>, since by default <span class="code">make</span> builds the first
target when none is explicitly given).  Then the following commands
would be performed:
<div class="programlisting">
   g++ -g -DDEBUG -c progA1.cpp
   g++ -g -DDEBUG -c progA2.cpp
   g++ -g -DDEBUG utilities.o progA1.o progA2.o
   mv a.out progA
</div>
Note that <span class="code">utilities.c</span> is not recompiled, because <span class="code">make</span>
would notice that <span class="code">utilities.o</span> already exists and was created
more recently than the last time when either <span class="code">utilities.c</span> or
<span class="code">utilities.h</span> was changed.</p>
  <p class="para">If you
want to test your makefile without actually performing the commands,
add a <span class="code">-n</span> option to your command (e.g., <span class="code">make -n progB</span>) and
<span class="code">make</span> will simply list the commands it would issue without
actually doing any of them.</p>
  <script type="text/javascript">
checkForAnchorOnOtherPage('section-1','section-1');
</script>
  <script type="text/javascript">
checkForAnchorOnOtherPage('section-2','section-2');
</script>
  <script type="text/javascript">
checkForAnchorOnOtherPage('artificial-targets','artificial-targets');
</script>
  <script type="text/javascript">
checkForAnchorOnOtherPage('writingMakefiles','writingMakefiles');
</script>
  <script type="text/javascript">
checkForAnchorOnOtherPage('section-5','section-5');
</script>
<script type="text/javascript">
checkForAnchorOnOtherPage('fn_fnote1','section-5');
</script><br/><table width="100%" class="navigationBar"><tr class="navigationBar"><td width="5%" class="navigationBar"><a class="navigationBarArrow" title="Next" href="http://cocoon.cs.odu.edu:80/cocoon/~cs252/open/make/section-1.html"><img class="navigationBar" src="_axle/next.gif" alt="Next"/></a></td><td width="5%" class="navigationBar"><a class="navigationBarArrow" title="Last" href="http://cocoon.cs.odu.edu:80/cocoon/~cs252/open/make/section-5.html"><img class="navigationBar" src="_axle/last.gif" alt="Last"/></a></td><td class="navigationBar"/><td width="5%" class="navigationBar"><a class="navigationBar" title="CS252 Home" href="http://cocoon.cs.odu.edu:80/cocoon/~cs252/directory/announcements.html"><img class="navigationBar" src="_axle/home.gif" alt="CS252 Home"/></a></td><td width="5%" class="navigationBar"><a class="navigationBar" title="discuss this page" href="http://cocoon.cs.odu.edu:80/cocoon/~cs252/forum/getXPath/open/make/make.html"><img class="navigationBar" src="_axle/forum.gif" alt="discuss this page"/></a></td></tr></table></body></html>