corner imagecorner image
FeaturesPluginsDocs & SupportCommunityPartners

Make Dependency Checking

Contents

Content on this page applies to NetBeans IDE 6.5

Requirements

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

Software or Resource Version Required
NetBeans IDE version 6.5 with NetBeans C/C++ pack
Java Developer Kit (JDK) version 6 or version 5

See the NetBeans IDE 6.5 Installation Instructions for information on 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 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 presence of #include directives that include one file's content into another file. 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 6.5 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, NetBeans 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

There is a checkbox in the Project Properties dialog box that controls dependency checking for each particular project. You may want to ensure that it's enabled:

Make Dependency Checking checkbox in project properties

There is also a checkbox in the Options window that sets the default state of the dependency checking feature for newly created projects:

Dependency checking checkbox in NetBeans options

Notes

  1. Automatic dependency checking works for managed C/C++ projects. For projects created from existing sources you have to rely on dependency checking logic (if any) in existing Makefile.
  2. Dependency checking requires support from your tool collection (make and compilers). It has been tested with the Sun tool collection and GNU tool collections including Cygwin and MinGW.
  3. Dependency checking works when Sun compilers are used together with Sun make, and GNU compilers with GNU make. Mixing Sun 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 make utility. When you build or clean your project from the GUI, NetBeans just invokes make, which executes the Makefile. This allows you to easily build your project outside of the IDE: just cd to your project directory and type make help to get instructions.

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

Makefiles used by NetBeans for C/C++ projects

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. Makefile-CONF.mk in the picture means that there are as many files as you have project configurations, e.g. Makefile-Release.mk, Makefile-Debug.mk, etc.

In the case of a managed project, NetBeans generates all the makefiles itself and inserts proper instructions for dependency checking. In the case of a project created from existing sources, dependency checking will work only if 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 makes and compilers. First, you should detect which make is running, and then generate corresponding dependency checking instructions.

Sun's make has a very simple solution. A special .KEEP_STATE: rule in Makefile instructs make to query 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 the solution is more complex. You have to explicitly ask 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 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 file .dep.inc. GNU make is detected by the presence of MAKE_VERSION variable. If MAKE_VERSION is not set, then Sun's 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.


References

  1. Wikipedia article about make
  2. Advanced Auto-Dependency Generation
Companion
Projects:
MySQL Database Server   GlassFish Community: an Open Source Application Server   Open Solaris  Open JDK: an Open SourceJDK   Mobile & Embedded Community     Sponsored by 
Sponsored by Sun Microsystems