Make Dependency Checking

This tutorial needs a review. You can edit it in GitHub following these contribution guidelines.

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 make utility through instructions in the Makefile .

netbeans stamp 80 74 73
Figure 1. Content on this page applies to the NetBeans IDE 7.3 and 7.4 and 8.0

Requirements

To follow this tutorial, you need the following software and resources.

Software Version Required

NetBeans IDE (including C/C++ support)

version 7.3, 7.4, or 8.0 with NetBeans C/C++ plugin

Java Development Kit (JDK)

version 7 or 8

See the NetBeans IDE Installation Instructions and Configuring the NetBeans IDE for C/C++/Fortran for information about downloading and installing the required software.

Introduction

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.

  • Full rebuild (Clean and Build action). It is slower, but guarantees a consistent build result.

  • Incremental rebuild (Build action). It is faster, but will it correctly rebuild everything that should be rebuilt?

The major problem with incremental rebuild is the presence of #include 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 ⇒ A includes C) make the problem even harder.

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.

Enabling Dependency Checking for a Project

Dependency checking can be controlled for each particular project. You may want to ensure that it’s enabled.

To enable dependency checking for a project:

  1. Right-click the project in the Projects window and choose Properties.

  2. In the Project Properties dialog box, select the Build node in the Categories list.

  3. In the build properties, select the checkbox for Enable Make Dependency Checking.

project checkbox

Enabling Dependency Checking by Default for New Projects

You can set a default state for dependency checking so that new projects you create are automatically enabled for make dependency checking.

To enable dependency checking for all new projects created in the IDE:

  1. Choose Tools > Options in the IDE main menu.

  2. Click the C/C++ button in the top pane.

  3. Click the Project Options tab.

  4. Select the checkbox for Enable dependency checking in generated makefiles

global checkbox

Notes

  • 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 Makefile . For projects created with existing sources you have to rely on dependency checking logic (if any) in the existing Makefile .

  • Dependency checking requires support from your tool collection ( make and compilers). It has been tested with the Oracle Solaris Studio tool collection and GNU tool collections including Cygwin and MinGW.

  • Dependency checking works when Oracle Solaris Studio compilers are used together with Oracle Solaris make and when GNU compilers are used with GNU gmake . Mixing Oracle Solaris make with GNU compilers and vice versa is not supported.

The rest of the article is for those advanced users who want to know what happens under the IDE’s hood.

Build Process (make and makefiles)

The build process of every C/C++ project in NetBeans is described in a Makefile , a file of special format understood by the make utility. When you build or clean your project from the GUI, the IDE invokes make , which executes the Makefile. This approach allows you to easily build your project outside of the IDE using make : just go to your project directory and type make help to get instructions.

Makefiles used by NetBeans IDE for a C/C++ project are shown below.

makefiles

The master Makefile is generated once and you can edit it manually. Makefiles in nbproject directory are not meant for manual editing; they are updated automatically by the IDE. The file Makefile-CONF.mk in the illustration represents multiple files for all your project configurations, such as Makefile-Release.mk , Makefile-Debug.mk , and so on.

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 Makefile contains such instructions, because the NetBeans IDE doesn’t change the existing Makefile .

Dependency Generation Basics

If you want make to check included file dependencies during build then you have to insert dependency information into the Makefile . Unfortunately there is no portable way to do this for all make utilities and compilers. First, you should detect which make is running, and then generate corresponding dependency checking instructions.

The Oracle Solaris make has a very simple solution. A special .KEEP_STATE: rule in the Makefile instructs make to query the compiler about included file dependencies and store them in a temporary file. Next time the project is rebuilt, make loads that temporary file, analyzes dependencies stored there, and determines which headers changed and which object files should be recompiled.

For GNU make (called gmake ) the solution is more complex. You have to explicitly ask the compiler to generate dependency information and then explicitly include it into the Makefile . 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 Makefile .

Implementation

The following code is added to nbproject/Makefile-impl.mk . It detects which make is running and puts corresponding dependency checking code into the file .dep.inc . GNU make is detected by the presence of MAKE_VERSION variable. If MAKE_VERSION is not set, then the Solaris make -specific instructions are generated.

# dependency checking support
.depcheck-impl:
	@echo "# This code depends on make tool being used" >.dep.inc
	@if [ -n "${MAKE_VERSION}" ]; then \
	    echo "DEPFILES=\$$(wildcard \$$(addsuffix .d, \$${OBJECTFILES}))" >>.dep.inc; \
	    echo "ifneq (\$${DEPFILES},)" >>.dep.inc; \
	    echo "include \$${DEPFILES}" >>.dep.inc; \
	    echo "endif" >>.dep.inc; \
	else \
	    echo ".KEEP_STATE:" >>.dep.inc; \
	    echo ".KEEP_STATE_FILE:.make.state.\$${CONF}" >>.dep.inc; \
	fi

The following code is added to nbproject/Makefile-${CONF}.mk . It instructs make to read previously generated .dep.inc and execute instructions from it.

# Enable dependency checking
.dep.inc: .depcheck-impl

include .dep.inc

The rule .dep.inc: .depcheck-impl is added to prevent build failure when .dep.inc does not exist. There is only one case when it happens: when you compile single file from the Projects window. In this case make executes file nbproject/Makefile-${CONF}.mk directly.

See Also

Please see the C/C++ Learning Trail for more articles about developing with C/C++/Fortran in NetBeans IDE.