The include system

The Waf preprocessor

Include paths are used by the c/c++ compilers for finding the headers. When one header changes, the files are recompiled automatically. Includes must be given in the following form:

def build(bld):
	bld.new_task_gen(
		features = 'cxx cprogram',
		source   = 'main.cpp',
		target   = 'test',
		includes = '. .. ../../')
			

Local folders are given relative to the folder of the current script. The equivalent build directory folder is then added automatically for headers or source files produced in the build directory.

Waf uses a preprocessor written in Python for adding the dependencies on the headers. A simple parser looking at #include statements would miss constructs such as:

#define mymacro "foo.h"
#include mymacro
		

Using the compiler for finding the dependencies would not work for applications requiring file preprocessing such as Qt. For Qt, special include files having the .moc extension must be detected by the build system and produced ahead of time. The c compiler could not parse such files.

#include "foo.moc"
		

Using the Waf preprocessor also makes the scripts strongly compiler-independent.

Portability recommandations

By default, the preprocessing does not climb to system headers. This may lead to missed depdendencies in the cases similar to the following:

#if SOMEMACRO
	/* an include in the project */
	#include "foo.h"
#endif
				

To write portable code and to ease debugging, it is strongly recommended to put all the conditions used in the project into a config.h file.

def configure(conf):
	conf.check(
		fragment='int main() { return 0; }\n',
		define_name='FOO',
		mandatory=1)
	conf.write_config_header('config.h')
				

Although it is discouraged, it is possible to enable the preprocessor to look into system headers by using the following code:

import preproc
preproc.go_absolute = True
				

Debugging dependencies

The Waf preprocessor contains a specific debugging zone:

$ waf --zones=preproc
				

To display the dependencies obtained or missed, use the following:

$ waf --zones=deps
				

The dependency computation is performed only when the files are not up-to-date, so these commands will display something only when there is a file to compile.