blob: 92079437da2672e0b2dfe22392b2c3d1d55f7a03 [file] [log] [blame]
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html><head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<meta name="keywords" content="NetBeans, IDE, Oracle Solaris Studio, integrated development environment, user, documentation, open source">
<meta name="description" content="This article describes the Make Dependency Checking feature for C and C++
projects in NetBeans IDE and Oracle Solaris Studio IDE. ">
<meta name="author" content="Alexey Vladykin">
<link rel="stylesheet" type="text/css" href="../../../netbeans.css">
<title>Make Dependency Checking - NetBeans IDE</title>
</head>
<body>
<a name="top"></a>
<h1>Make Dependency Checking</h1>
<div class="articledate" style="margin-left: 0px;font-style:italic;">
Contributed by Alexey Vladykin<br>
March 2014 [Revision number: V8.0-1]
</div>
<!-- maintained by susanm -->
<p>This tutorial shows you how to enable the NetBeans IDE to check file dependencies in your projects when
building. Dependency checking is performed by the <tt>make</tt> utility through instructions in the <tt>Makefile</tt>.</p>
<p><b>Contents</b></p>
<img src="../../../images_www/articles/73/netbeans-stamp-80-74-73.png" class="stamp"
alt="Content on this page applies to NetBeans IDE 7.3 and 7.4 and 8.0"
title="Content on this page applies to the NetBeans IDE 7.3 and 7.4 and 8.0">
<ul class="toc">
<li><a href="#requirements" title="Requirements">Requirements</a></li>
<li><a href="#introduction" title="Introduction">Introduction</a></li>
<li><a href="#build" title="Build Process (make and Makefiles)">Build Process (make and
Makefiles)</a></li>
<li><a href="#basics" title="Dependency Generation Basics">Dependency Generation Basics</a></li>
<li><a href="#implementation" title="Implementation">Implementation</a></li>
</ul>
<h2><A NAME="requirements"></a>Requirements</h2>
<p><b>To follow this tutorial, you need the following software and resources.</b> </p>
<table>
<tbody>
<tr>
<th class="tblheader" scope="col">Software</th>
<th class="tblheader" scope="col">Version Required</th>
</tr>
<tr>
<td class="tbltd1">NetBeans IDE (including C/C++ support)</td>
<td class="tbltd1"><a href="https://netbeans.org/downloads/index.html">version 7.3, 7.4, or 8.0 with NetBeans C/C++ plugin</a></td>
</tr>
<tr>
<td class="tbltd1">Java Development Kit (JDK)</td>
<td class="tbltd1"><a href="http://www.oracle.com/technetwork/java/javase/downloads/index.html">version 7 or 8</a></td>
</tr>
</tbody>
</table>
<br>
<p>See the <a href="../../../community/releases/80/install.html">NetBeans IDE
Installation
Instructions</a> and <a
HREF="../../../community/releases/80/cpp-setup-instructions.html">
Configuring the NetBeans IDE for C/C++/Fortran</a><br> for
information about downloading and installing the required software.</p>
<h2><a name="introduction"></a>Introduction</h2>
<p>
Large C/C++ projects consist of thousands of files. For example, the Linux kernel
has about 20,000 files. If you are developing such a project and want
to rebuild it after a small change - say, a one line fix -
there are two options.
<ul>
<li>
Full rebuild (Clean and Build action). It is slower,
but guarantees a consistent build result.
</li>
<li>
Incremental rebuild (Build action). It is faster,
but will it correctly rebuild everything that should be rebuilt?
</li>
</ul>
<p>
The major problem with incremental rebuild is the presence of <tt>#include</tt>
directives, which include one file's content into another file. The included file
is known as a file dependency. Modification
of the included file should be treated as modification of all files that
include it. Indirect includes (A includes B, B includes C =&gt; A includes C)
make the problem even harder.
</p>
<p>
NetBeans IDE supports automatic checking of file dependencies and
does its best to make incremental rebuild work correctly. If you change
a header file that is included into some of your source files and then
click Build, the IDE will rebuild only those
parts of the project that really depend on the changed header.
This feature saves time and guarantees consistent build results.
</p>
<h3>Enabling Dependency Checking for a Project</h3>
<p>
Dependency checking can be controlled for each particular project.
You may want to ensure that it's enabled.
</p>
<p><b>To enable dependency checking for a project:</b></p>
<ol>
<li>Right-click the project in the Projects window and choose Properties.</li>
<li>
In the Project Properties dialog box, select the Build node in the Categories list.
</li>
<li>In the build properties, select the checkbox for Enable Make Dependency Checking.</li>
</ol>
<br>
<img src="../../../images_www/articles/73/cnd/depchecking/project-checkbox.png"
alt="Make Dependency Checking checkbox in project properties" class="margin-around">
<br>
<h3>Enabling Dependency Checking by Default for New Projects</h3>
<p>You can set a default state for dependency checking so that new projects you create are automatically
enabled for make dependency checking.</p>
<p><b>To enable dependency checking for all new projects created in the IDE:</b></p>
<ol>
<li>Choose Tools &gt; Options in the IDE main menu.</li>
<li>
Click the C/C++ button in the top pane.
</li>
<li>Click the Project Options tab.</li>
<li>Select the checkbox for Enable dependency checking in generated makefiles</li>
</ol>
<br>
<img src="../../../images_www/articles/73/cnd/depchecking/global-checkbox.png"
alt="Dependency checking checkbox in NetBeans options" class="margin-around">
<h3 class="notes">Notes</h3>
<ul>
<li>
Automatic dependency checking works for C/C++ projects that were created in the IDE
(managed projects). The IDE builds dependency checking logic into the generated <tt>Makefile</tt>.
For projects created with existing sources you have to rely on dependency
checking logic (if any) in the existing <tt>Makefile</tt>.
</li>
<li>
Dependency checking requires support from your tool collection
(<tt>make</tt> and compilers). It has been tested with the Oracle Solaris Studio tool collection
and GNU tool collections including Cygwin and MinGW.
</li>
<li>
Dependency checking works when Oracle Solaris Studio compilers are used together with
Oracle Solaris <tt>make</tt> and when GNU compilers are used with GNU <tt>gmake</tt>.
Mixing Oracle Solaris <tt>make</tt> with GNU compilers and vice versa is not supported.
</li>
</ul>
<p>
The rest of the article is for those advanced users who
want to know what happens under the IDE's hood.
</p>
<h2><a name="build"></a>Build Process (make and makefiles)</h2>
<p>
The build process of every C/C++ project in NetBeans is described
in a <tt>Makefile</tt>, a file of special format understood by the
<tt>make</tt> utility. When you build or clean your project from the GUI,
the IDE invokes <tt>make</tt>, which executes the Makefile. This approach
allows you to easily build your project outside of the IDE using <tt>make</tt>:
just go to your project directory and type <tt>make help</tt> to get instructions.
</p>
<p>
Makefiles used by NetBeans IDE for a C/C++ project are shown
below.
</p>
<img src="../../../images_www/articles/73/cnd/depchecking/makefiles.png" alt="Makefiles used by NetBeans for C/C++ projects" class="margin-around">
<p>
The master <tt>Makefile</tt> is generated once and you can edit it manually.
Makefiles in <tt>nbproject</tt> directory are not meant for manual
editing; they are updated automatically by the IDE. The file
<tt>Makefile-<i>CONF</i>.mk</tt> in the illustration represents multiple files for all your
project configurations,
such as <tt>Makefile-Release.mk</tt>, <tt>Makefile-Debug.mk</tt>, and so on.
</p>
<p>
For a managed project, the IDE generates all the makefiles itself
and inserts proper instructions for dependency checking. For
a project created from existing sources, dependency checking will
work only if the existing <tt>Makefile</tt> contains such instructions,
because the NetBeans IDE doesn't change the existing <tt>Makefile</tt>.
</p>
<h2><a name="basics"></a>Dependency Generation Basics</h2>
<p>
If you want <tt>make</tt> to check included file dependencies during build
then you have to insert dependency information into the <tt>Makefile</tt>.
Unfortunately there is no portable way to do this for all <tt>make</tt> utilities
and compilers. First, you should detect which <tt>make</tt> is running,
and then generate corresponding dependency checking instructions.
</p>
<p>
The Oracle Solaris <tt>make</tt> has a very simple solution. A special <tt>.KEEP_STATE:</tt>
rule in the <tt>Makefile</tt> instructs <tt>make</tt> to query the compiler about included
file dependencies and store them in a temporary file. Next time
the project is rebuilt, <tt>make</tt> loads that temporary file,
analyzes dependencies stored there, and determines which headers changed
and which object files should be recompiled.
</p>
<p>
For GNU <tt>make</tt> (called <tt>gmake</tt>) the solution is more complex. You have to explicitly
ask the compiler to generate dependency information and then explicitly
include it into the <tt>Makefile</tt>. The idea is to pass special flags
to the compiler, so that the compiler will generate dependency information
for each compiled source file. Next time the project is rebuilt, dependency
information is collected and included into the <tt>Makefile</tt>.
</p>
<h2><a name="implementation"></a>Implementation</h2>
<p>
The following code is added to <tt>nbproject/Makefile-impl.mk</tt>.
It detects which <tt>make</tt> is running and puts corresponding
dependency checking code into the file <tt>.dep.inc</tt>. GNU <tt>make</tt> is detected
by the presence of <tt>MAKE_VERSION</tt> variable. If <tt>MAKE_VERSION</tt>
is not set, then the Solaris <tt>make</tt>-specific instructions are generated.
</p>
<pre class="examplecode"># dependency checking support
.depcheck-impl:
@echo "# This code depends on make tool being used" &gt;.dep.inc
@if [ -n "${MAKE_VERSION}" ]; then \
echo "DEPFILES=\$$(wildcard \$$(addsuffix .d, \$${OBJECTFILES}))" &gt;&gt;.dep.inc; \
echo "ifneq (\$${DEPFILES},)" &gt;&gt;.dep.inc; \
echo "include \$${DEPFILES}" &gt;&gt;.dep.inc; \
echo "endif" &gt;&gt;.dep.inc; \
else \
echo ".KEEP_STATE:" &gt;&gt;.dep.inc; \
echo ".KEEP_STATE_FILE:.make.state.\$${CONF}" &gt;&gt;.dep.inc; \
fi</pre>
<p>
The following code is added to <tt>nbproject/Makefile-${CONF}.mk</tt>.
It instructs <tt>make</tt> to read previously generated <tt>.dep.inc</tt>
and execute instructions from it.
</p>
<pre class="examplecode"># Enable dependency checking
.dep.inc: .depcheck-impl
include .dep.inc</pre>
<p>
The rule <tt>.dep.inc: .depcheck-impl</tt> is added to prevent build
failure when <tt>.dep.inc</tt> does not exist. There is only one case
when it happens: when you compile single file from the Projects window.
In this case <tt>make</tt> executes file <tt>nbproject/Makefile-${CONF}.mk</tt>
directly.
</p>
<h2>References</h2>
<ol>
<li>
<a href="http://en.wikipedia.org/wiki/Make_%28software%29" target="_blank">Wikipedia article about <tt>make</tt></a>
</li>
<li>
<a href="http://make.paulandlesley.org/autodep.html" target="_blank">Advanced Auto-Dependency Generation</a>
</li>
</ol>
<h2>See Also</h2>
<p>Please see the
<a href="https://netbeans.org/kb/trails/cnd.html">C/C++ Learning Trail</a> for
more articles about developing with C/C++/Fortran in NetBeans IDE.</p>
<div class="feedback-box"><a href="mailto:users@cnd.netbeans.org?subject=Feedback:%20Make%20Dependency%20Checking%20-%20NetBeans%20IDE%208.0%20Tutorial">Send Feedback on This Tutorial</a></div>
</body></html>