Sophie

Sophie

distrib > Mandriva > 2010.0 > i586 > media > contrib-release > by-pkgid > 2053a0d9eaaf755b990f80ce4df504a7 > files > 29

waf-1.5.9-1mdv2010.0.noarch.rpm

<?xml version='1.0'?>
<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
"http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd"
>
<chapter id="configuration">
	<title>The configuration system</title>

	<section id="config_overview">
		<title>Overview of the configuration files</title>
		<para>
			Configuring a project consists in finding the parameters that will be used during the build step
			<programlisting language="python">
$ cd demos/simple_scenarios/init
$ cat wscript

VERSION='0.0.1'
APPNAME='test'
srcdir = '.'
blddir = 'build'

def configure(conf):
        pass
def build(bld):
        pass

$ waf configure
			</programlisting>
			Several configuration files are produced and the configuration parameters are stored in the folder <emphasis>c4che</emphasis> located under the build directory
			<programlisting language="sh">
|-- .lock-wscript <co id="lock-co" linkends="lock"/>
`-- build
    |-- .wafpickle-6 <co id="pickle-co" linkends="pickle"/>
    |-- c4che
    |   |-- build.config.py <co id="bldconf-co" linkends="bldconf"/>
    |   `-- default.cache.py <co id="env-co" linkends="env"/>
    `-- config.log <co id="log-co" linkends="log"/>
			</programlisting>
			<calloutlist>
				<callout arearefs="lock-co" id="lock">
					<para>Contains a reference to the build directory and contains the command-line configuration flags. It is located at the root of the source directory.</para>
				</callout>
				<callout arearefs="pickle-co" id="pickle">
					<para>Contains serialized data corresponding to the build information (cache, filesystem representation, etc)</para>
				</callout>
				<callout arearefs="bldconf-co" id="bldconf">
					<para>Contains the Waf version and the list of Waf modules to open automatically</para>
				</callout>
				<callout arearefs="env-co" id="env">
					<para>Represents a configuration environment (parameters such as configuration flags used during the build)</para>
				</callout>
				<callout arearefs="log-co" id="log">
					<para>Contains the configuration test execution details</para>
				</callout>
			</calloutlist>
			The file <emphasis>default.cache.py</emphasis> is called a configuration environment, and it may be edited by hand. We will give the details on the following section. The other files are not meant to be modified by hand, even if they are editable.
		</para>
	</section>

	<section id="config_env">
		<title>The configuration environments</title>
		<para>
			The build phase uses configuration environments created during the configuration phase. The configuration environments are <emphasis><ulink url="http://docs.python.org/tutorial/datastructures.html#dictionaries">Python Dictionaries</ulink></emphasis> which map keys to values. The configuration environment files created take the following form:
			<programlisting language="python">
$ cat build/c4che/default.cache.py
CXXFLAGS = ['-O2', '-Wall']
			</programlisting>
		</para>
		<para>
			By default, the conf object comes with a default built-in configuration environment:
			<programlisting language="python">
def configure(conf):
	conf.env.append_value('CXXFLAGS', '-O2')
			</programlisting>
			To replace the default configuration environment, a new one must be created and assigned:
			<programlisting language="python">
def configure(conf):
	conf.env.append_value('CXXFLAGS', '-O2')
	env2 = conf.env.copy() <co id="dup-co" linkends="dup"/>
	conf.set_env_name('debug', env2) <co id="name-co" linkends="name"/>
	conf.setenv('debug') <co id="repl-co" linkends="repl"/>
	conf.env.append_value('CXXFLAGS', '-g') <co id="mod-co" linkends="mod"/>
			</programlisting>
			<calloutlist>
				<callout arearefs="dup-co" id="dup">
					<para>Duplicates the default configuration environment (shallow copy)</para>
				</callout>
				<callout arearefs="name-co" id="name">
					<para>Binds the configuration environment to the name 'debug'</para>
				</callout>
				<callout arearefs="repl-co" id="repl">
					<para>Replaces the default configuration environment by the 'debug' one</para>
				</callout>
				<callout arearefs="mod-co" id="mod">
					<para>Changes the CXXFLAGS entry in the 'debug' configuration environment. Since we are using a shallow copy, we have to use the methods <emphasis>append_value</emphasis>, <emphasis>prepend_value</emphasis> or <emphasis>append_unique</emphasis> instead of '+=' or '[].append'</para>
				</callout>
			</calloutlist>
			In the previous example, the file contents will be:
			<programlisting language="sh">
$ tree build
`-- build
    |-- c4che
    |   |-- default.cache.py
    |   |-- debug.cache.py

$ cat build/c4che/default.cache.py
CXXFLAGS = ['-O2']

$ cat build/c4che/debug.cache.py
CXXFLAGS = ['-g']
			</programlisting>
		</para>
		<para>
			In the build section, the values are retrieved using <emphasis>bld.env_of_name</emphasis>, for example
			<programlisting language="python">
def build(bld):
	print(bld.env_of_name('default')['CXXFLAGS'])
	print(bld.env_of_name('debug')['CXXFLAGS'])
			</programlisting>
		</para>
	</section>

	<section id="config_helper_execution">
		<title>Configuration helper execution</title>
		<para>
			Configuration helpers are methods provided by the conf object to help finding parameters, for example the method <emphasis>conf.find_program</emphasis>
			<programlisting language="python">
def configure(conf):
	conf.find_program('test')
			</programlisting>
			When a test fails, the exception <emphasis>Configure.ConfigurationException</emphasis> is raised.
		</para>

		<para>
			When calling the configuration from a tool, for example:
			<programlisting language="python">
def configure(conf):
	conf.check_tool('g++')
			</programlisting>
			several different configuration helpers may be called: the first one for finding the compiler and the others for finding compiler flags. In some cases, it is interesting to disable some tests (unnecessary, time consuming, etc), to insert new tests, or to modify the existing tests. The <emphasis>check_tool</emphasis> method has a parameter for passing the list of checks to perform:
			<programlisting language="python">
def configure(conf):
	conf.check_tool('g++', funs="find_gxx find_cpp find_ar gxx_common_flags")
			</programlisting>
			If no check is performed, the configuration helpers are still attached to the conf object, and may be used later:
			<programlisting language="python">
def configure(conf):
	conf.check_tool('g++', funs=[])
	conf.find_gxx()
			</programlisting>
			To ease the creation of projects split into modules, conf.check_tool will not load the tools twice for the same environment and the same parameters.
		</para>

		<para>
			An error handler attached to the conf object is used for catching the Configuration exceptions and processing the errors. Here is how to replace the default configuration error handler by a custom method which may modify the list of tests, stop the evaluation, or re-raise the exception:
			<programlisting language="python">
import Configure, Constants
@conf
def error_handler(fun, exc):
	print('exception %r' % exc)
	# other optionals return values: Constants.CONTINUE or anything else to re-raise the exception
	return Constants.BREAK
			</programlisting>
			The following diagram illustrates the test execution loop performed from conf.check_tool
			<graphic format="png" fileref="conftest.png" align="center"/>
		</para>
	</section>

	<section id="adding_config_helpers">
		<title>Adding new configuration helpers</title>
		<para>
			The configuration tests specific for the different languages belong to the different Waf tools representing the languages supported. For example, The configuration tests for the C language are located in the tool <filename>config_c.py</filename>.
			To enable this, decorators are used to attach new configuration tests dynamically, for example:
			<programlisting language="python">
from Configure import conf

@conf
def get_define(self, define):
	"get the value of a previously stored define"
	try: return self.env.defines[define]
	except KeyError: return None
			</programlisting>
			Then the new configuration test may be used easily in wscript:
			<programlisting language="python">
def configure(conf):
	print(conf.get_define('DEBUG'))
			</programlisting>
		</para>
	</section>
</chapter>