The Waf features are names linked to specific functions by the decorator :py:func:`waflib.TaskGen.feature`. The functions are mapped to the class :py:class:`waflib.TaskGen.task_gen` as methods. The association between feature names and methods is *many-to-many*, which means that a method may be involved in several features, and that a feature may be bound to several methods. Here is how to create and use a new feature named **foo**:: from waflib.TaskGen import feature @feature('foo') def print_hello(self): print("Hello, World!") The function *print_hello* is now associated with the :py:class:`waflib.TaskGen.task_gen` class, which means that it may be used directly:: def build(bld): tg = bld() tg.print_hello() The method may be called directly, and several times. If a method creates task, the same tasks will be created more than once, which may cause build errors. The *feature* attribute is used to have the associated methods called *exactly once* before the build starts:: def build(bld): bld(features='foo') Here is a more complete example with two methods:: from waflib.TaskGen import feature, after_method @feature('foo') @after_method('print_bar') def print_hello(self): print("Hello, Foo!") @feature('bar') def print_bar(self): print("Hello, Bar!") def build(bld): bld(features='foo bar') The order of method execution is unrelated to the order of the features given. For instance, this example will print "Hello, Bar!" then "Hello, Foo!". The decorators :py:func:`waflib.TaskGen.after` and :py:func:`waflib.TaskGen.before` are enforcing partial order constraints on the methods to execute. The following maps represent the associations betwen feature methods (represented in yellow) and methods associated to other feature names.