1179860b2SJed Brown<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"> 2179860b2SJed Brown<book id="BuildSystemManual" lang="en"> 3179860b2SJed Brown 4179860b2SJed Brown<bookinfo> 5179860b2SJed Brown<title>ASE BuildSystem Manual</title> 6179860b2SJed Brown<authorgroup> 7179860b2SJed Brown<author> 8179860b2SJed Brown<firstname>Matthew</firstname> 9179860b2SJed Brown<othername>G.</othername> 10179860b2SJed Brown<surname>Knepley</surname> 11179860b2SJed Brown</author> 12179860b2SJed Brown</authorgroup> 13179860b2SJed Brown<date>July, 2005</date> 14179860b2SJed Brown<releaseinfo>Release tag ???</releaseinfo> 15179860b2SJed Brown</bookinfo> 16179860b2SJed Brown 17179860b2SJed Brown<chapter id="Introduction"> 18179860b2SJed Brown<title>Introduction</title> 19179860b2SJed Brown 20179860b2SJed Brown<para>The BuildSystem from ASE is intended to be a Python replacement for the GNU autotools. It actually encompasses 21179860b2SJed Brownsomewhat more, as it supports integrated version control and automatic code generation. However, the most useful 22179860b2SJed Browncomparisons will come from <command>autoconf</command>, <command>make</command>, and <command>libtool</command>. The 23179860b2SJed Brownsystem is not designed to be monolithic. Thus each component may be used independently, meaning logging, configuration, 24179860b2SJed Brownand build are all separate modules which do not require each other. This allows a user to incremenetally adopt the most 25179860b2SJed Brownuseful portions of the package.</para> 26179860b2SJed Brown 27179860b2SJed Brown</chapter> 28179860b2SJed Brown 29179860b2SJed Brown<chapter id="Configure"> 30179860b2SJed Brown<title>Configure</title> 31179860b2SJed Brown 32179860b2SJed Brown<sect1 id="Configure-Design-Sketch"> 33179860b2SJed Brown<title>Configure Design Sketch</title> 34179860b2SJed Brown 35179860b2SJed Brown<para>The system is based upon an autonomous unit, objects of class <classname>config.base.Configure</classname>, which 36179860b2SJed Brownare responsible for discovering configuration information for a particular package or purpose. The only interface which 37179860b2SJed Brownmust be supported is the <methodname>configure</methodname> method, as shown below. Support for lower-level operations 38179860b2SJed Brownsuch as compiling and linking will be discussed in section ???.</para> 39179860b2SJed Brown 40179860b2SJed Brown<classsynopsis language="python"> 41179860b2SJed Brown<ooclass> 42179860b2SJed Brown<classname>Configure</classname> 43179860b2SJed Brown</ooclass> 44179860b2SJed Brown<methodsynopsis> 45179860b2SJed Brown<void/><methodname>configure</methodname><methodparam><parameter>self</parameter></methodparam> 46179860b2SJed Brown</methodsynopsis> 47179860b2SJed Brown</classsynopsis> 48179860b2SJed Brown 49179860b2SJed Brown<para>This collection of configure objects is managed by a <classname>config.base.Framework</classname> object. As we 50179860b2SJed Brownwill see in section ???, the framework manages all dependecies between modules and output of configure information. The 51179860b2SJed Brownframework is itself a subclass of <classname>config.base.Configure</classname> for which the 52179860b2SJed Brown<methodname>configure</methodname> method manages the entire configuration process. In order to associate a module with 53179860b2SJed Brownthe given framework, it also provides the <methodname>require</methodname> method, discussed in section ???. Thus, the 54179860b2SJed Brownminimal framework interface is given by:</para> 55179860b2SJed Brown 56179860b2SJed Brown<classsynopsis language="python"> 57179860b2SJed Brown<ooclass> 58179860b2SJed Brown<classname>Framework</classname> 59179860b2SJed Brown</ooclass> 60179860b2SJed Brown<ooclass> 61179860b2SJed Brown<classname>config.base.Configure</classname> 62179860b2SJed Brown</ooclass> 63179860b2SJed Brown<methodsynopsis> 64179860b2SJed Brown<void/><methodname>require</methodname> 65179860b2SJed Brown <methodparam><parameter>self</parameter></methodparam> 66179860b2SJed Brown <methodparam><parameter>moduleName</parameter></methodparam> 67179860b2SJed Brown <methodparam><parameter>depChild</parameter></methodparam> 68179860b2SJed Brown <methodparam><parameter>keywordArgs</parameter><initializer>{}</initializer></methodparam> 69179860b2SJed Brown</methodsynopsis> 70179860b2SJed Brown<methodsynopsis> 71179860b2SJed Brown<void/><methodname>configure</methodname><methodparam><parameter>self</parameter></methodparam> 72179860b2SJed Brown</methodsynopsis> 73179860b2SJed Brown</classsynopsis> 74179860b2SJed Brown 75179860b2SJed Brown<para>This design allows user modules to be seamlessly integrated into the framework without changing the paradigm, or 76179860b2SJed Browneven any of the original code. Modules can be specified on the command line, or left in special directories. Although it 77179860b2SJed Brownis common to derive from <classname>config.base.Configure</classname>, the only necessity is that the user provide a 78179860b2SJed Brown<methodname>configure</methodname> method for the framework to execute.</para> 79179860b2SJed Brown 80179860b2SJed Brown<para>The framework does provide the traditional output mechanisms from <command>autoconf</command>, namely 81179860b2SJed Brown<methodname>#define</methodname> statements and file substitutions, to which we add make variables and 82179860b2SJed Brownrules. However, the preferred interaction mechanism is to use member variables directly from the configure objects. This 83179860b2SJed Brownis illustrated in section ???</para> 84179860b2SJed Brown 85179860b2SJed Brown</sect1> 86179860b2SJed Brown 87179860b2SJed Brown<sect1 id="Running-configure"> 88179860b2SJed Brown<title>Running configure</title> 89179860b2SJed Brown 90179860b2SJed Brown<para>The first step in running configure is to show the help: 91179860b2SJed Brown<screen> 92179860b2SJed Brown<prompt>bash$</prompt> <command>framework.py -help</command> 93179860b2SJed Brown<computeroutput> 94179860b2SJed BrownPython Configure Help 95*bebe2cf6SSatish Balay Comma separated lists should be given between [] (use \[ \] in tcsh/csh) 96179860b2SJed Brown For example: --with-mpi-lib=\[/usr/local/lib/libmpich.a,/usr/local/lib/libpmpich.a\] 97179860b2SJed Brown---------------------------------------------------------------------------------------- 98179860b2SJed BrownScript: 99179860b2SJed Brown --help : Print this help message current: 1 100179860b2SJed Brown --h : Print this help message current: 0 101179860b2SJed BrownFramework: 102179860b2SJed Brown --configModules : A list of Python modules with a Configure class current: [] 103179860b2SJed Brown --ignoreCompileOutput : Ignore compiler output current: 1 104179860b2SJed Brown --ignoreLinkOutput : Ignore linker output current: 1 105179860b2SJed Brown --ignoreWarnings : Ignore compiler and linker warnings current: 0 106179860b2SJed Brown --doCleanup : Delete any configure generated files (turn off for debugging) current: 1 107179860b2SJed Brown --with-alternatives : Provide a choice among alternative package installations current: 0 108179860b2SJed Brown --search-dirs : A list of directories used to search for executables current: [] 109179860b2SJed Brown --package-dirs : A list of directories used to search for packages current: [] 110179860b2SJed Brown --with-batch : Machine uses a batch system to submit jobs current: 0 111179860b2SJed Brown</computeroutput> 112179860b2SJed Brown</screen> 113179860b2SJed BrownThe options shown will depend upon the modules loaded with <option>-configModules</option>. For instance, we will 114179860b2SJed Brownnormally load the compiler module, which reveals the host of optios controlling preprocessors, compilers, and linkers. 115179860b2SJed Brown<screen> 116179860b2SJed Brown<prompt>bash$</prompt> <command>framework.py -configModules=[config.compilers] -help</command> 117179860b2SJed Brown<computeroutput> 118179860b2SJed BrownPython Configure Help 119*bebe2cf6SSatish Balay Comma separated lists should be given between [] (use \[ \] in tcsh/csh) 120179860b2SJed Brown For example: --with-mpi-lib=\[/usr/local/lib/libmpich.a,/usr/local/lib/libpmpich.a\] 121179860b2SJed Brown---------------------------------------------------------------------------------------- 122179860b2SJed BrownScript: 123179860b2SJed Brown --help : Print this help message current: 1 124179860b2SJed Brown --h : Print this help message current: 0 125179860b2SJed BrownFramework: 126179860b2SJed Brown --configModules : A list of Python modules with a Configure class current: [] 127179860b2SJed Brown --ignoreCompileOutput : Ignore compiler output current: 1 128179860b2SJed Brown --ignoreLinkOutput : Ignore linker output current: 1 129179860b2SJed Brown --ignoreWarnings : Ignore compiler and linker warnings current: 0 130179860b2SJed Brown --doCleanup : Delete any configure generated files (turn off for debugging) current: 1 131179860b2SJed Brown --with-alternatives : Provide a choice among alternative package installations current: 0 132179860b2SJed Brown --search-dirs : A list of directories used to search for executables current: [] 133179860b2SJed Brown --package-dirs : A list of directories used to search for packages current: [] 134179860b2SJed Brown --with-batch : Machine uses a batch system to submit jobs current: 0 135179860b2SJed BrownCompilers: 136179860b2SJed Brown --with-cpp=<prog> : Specify the C preprocessor 137179860b2SJed Brown --with-cc=<prog> : Specify the C compiler 138179860b2SJed Brown --with-cxx=<prog> : Specify the C++ compiler 139179860b2SJed Brown --with-fc=<prog> : Specify the Fortran compiler 140179860b2SJed Brown --with-gnu-compilers=<bool> : Try to use GNU compilers current: 1 141179860b2SJed Brown --with-vendor-compilers=<vendor> : Try to use vendor compilers (no argument all vendors, 0 no vendors) current: 142179860b2SJed Brown --with-64-bit-pointers=<bool> : Use 64 bit compilers and libraries current: 0 143179860b2SJed Brown --CPP=<prog> : Specify the C preprocessor 144179860b2SJed Brown --CPPFLAGS=<string> : Specify the C preprocessor options current: 145179860b2SJed Brown --CXXPP=<prog> : Specify the C++ preprocessor 146179860b2SJed Brown --CC=<prog> : Specify the C compiler 147179860b2SJed Brown --CFLAGS=<string> : Specify the C compiler options current: 148179860b2SJed Brown --CXX=<prog> : Specify the C++ compiler 149179860b2SJed Brown --CXXFLAGS=<string> : Specify the C++ compiler options current: 150179860b2SJed Brown --CXX_CXXFLAGS=<string> : Specify the C++ compiler-only options current: 151179860b2SJed Brown --FC=<prog> : Specify the Fortran compiler 152179860b2SJed Brown --FFLAGS=<string> : Specify the Fortran compiler options current: 153179860b2SJed Brown --LD=<prog> : Specify the default linker 154179860b2SJed Brown --CC_LD=<prog> : Specify the linker for C only 155179860b2SJed Brown --CXX_LD=<prog> : Specify the linker for C++ only 156179860b2SJed Brown --FC_LD=<prog> : Specify the linker for Fortran only 157179860b2SJed Brown --LDFLAGS=<string> : Specify the linker options current: 158179860b2SJed Brown --with-ar : Specify the archiver 159179860b2SJed Brown -AR : Specify the archiver flags 160179860b2SJed Brown -AR_FLAGS : Specify the archiver flags 161179860b2SJed Brown --with-ranlib : Specify ranlib 162179860b2SJed Brown --with-shared-libraries : Enable shared libraries current: 1 163179860b2SJed Brown --with-shared-ld=<prog> : Specify the shared linker 164179860b2SJed Brown --with-f90-header=<file> : Specify the C header for the F90 interface, e.g. f90_intel.h 165179860b2SJed Brown --with-f90-source=<file> : Specify the C source for the F90 interface, e.g. f90_intel.c 166179860b2SJed Brown</computeroutput> 167179860b2SJed Brown</screen> 168179860b2SJed BrownThe syntax for list and dictionary option values is identical to Python syntax. However, in some shells (like 169179860b2SJed Brown<command>csh</command>), brackets must be escaped, and braces will usually have to be enclosed in quotes.</para> 170179860b2SJed Brown 171179860b2SJed Brown<para>The modules indicated with <option>-configModules</option> are located using <envar>PYTHONPATH</envar>. Since 172179860b2SJed Brownspecifying environment variables can be inconvenient and error prone, it is common to provide a driver which alters 173179860b2SJed Brown<varname>sys.path</varname>, as is done for PETSc. In fact, the PETSc driver 174179860b2SJed Brown<itemizedlist> 175179860b2SJed Brown <listitem><para>Verifies <envar>PETSC_ARCH</envar></para></listitem> 176179860b2SJed Brown <listitem><para>Checks for invalid Cygwin versions</para></listitem> 177179860b2SJed Brown <listitem><para>Checks for RedHat 9, which has a threads bug</para></listitem> 178179860b2SJed Brown <listitem><para>Augments <envar>PYTHONPATH</envar></para></listitem> 179179860b2SJed Brown <listitem><para>Adds the default PETSc configure module</para></listitem> 180179860b2SJed Brown <listitem><para>Persists the configuration in <filename>RDict.db</filename></para></listitem> 181179860b2SJed Brown <listitem><para>Handles exceptions</para></listitem> 182179860b2SJed Brown</itemizedlist> 183179860b2SJed Brown</para> 184179860b2SJed Brown 185179860b2SJed Brown</sect1> 186179860b2SJed Brown 187179860b2SJed Brown<sect1 id="Adding-a-module"> 188179860b2SJed Brown<title>Adding a module</title> 189179860b2SJed Brown 190179860b2SJed Brown<para>As we discussed in the introduction, all that is strictly necessary for a configure module, is to provide a class 191179860b2SJed Brownnamed <classname>Configure</classname> with a method <methodname>configure</methodname> taking no arguments. However, 192179860b2SJed Brownthere are a variety of common operations, which will be illustrated in the sections below.</para> 193179860b2SJed Brown 194179860b2SJed Brown <sect2 id="Using-other-modules"> 195179860b2SJed Brown <title>Using other modules</title> 196179860b2SJed Brown 197179860b2SJed Brown <para>We will often want to use the methods or results of other configure modules in order to perform checks in our 198179860b2SJed Brownown. The framework provides a mechanism for retrieving the object for any given configure module. As an example, 199179860b2SJed Brownconsider checking for the <methodname>ddot</methodname> function in the BLAS library. The relevant Python code would 200179860b2SJed Brownbe 201179860b2SJed Brown<programlisting> 202179860b2SJed Brownimport config.base 203179860b2SJed Brown 204179860b2SJed Brownclass Configure(config.base.Configure): 205179860b2SJed Brown def __init__(self, framework): 206179860b2SJed Brown config.base.Configure.__init__(self, framework) 207179860b2SJed Brown self.compilers = self.framework.require('config.compilers', self) 208179860b2SJed Brown self.libraries = self.framework.require('config.libraries', self) 209179860b2SJed Brown return 210179860b2SJed Brown 211179860b2SJed Brown def configure(self): 212179860b2SJed Brown return self.libraries.check('libblas.a', 'ddot', otherLibs = self.compilers.flibs, 213179860b2SJed Brown fortranMangle = 1) 214179860b2SJed Brown</programlisting> 215179860b2SJed BrownThe <methodname>require</methodname> call will return the configure object from the given module, creating it if 216179860b2SJed Brownnecessary. If the second argument is given, the framework will ensure that the returned configure object runs 217179860b2SJed Brown<emphasis>before</emphasis> the passed configure object. Notice that we can use the returned object either to call 218179860b2SJed Brownmethods, like <methodname>check</methodname> from <classname>config.libraries</classname>, or use member variables, such 219179860b2SJed Brownas the list of Fortran compatibility libraries <methodname>flibs</methodname> from 220179860b2SJed Brown<classname>config.compilers</classname>. 221179860b2SJed Brown</para> 222179860b2SJed Brown 223179860b2SJed Brown<para>The underlying implementation in the framework uses a directed acyclic graph to indicate dependencies among 224179860b2SJed Brownmodules. The vertices of this graph, configure objects, are topologically sorted and then executed. Moreover, child 225179860b2SJed Brownobjects can be added to the framework without respecting the dependency structure, but this is discouraged.</para> 226179860b2SJed Brown 227179860b2SJed Brown </sect2> 228179860b2SJed Brown 229179860b2SJed Brown <sect2 id="Adding-a-test"> 230179860b2SJed Brown <title>Adding a test</title> 231179860b2SJed Brown 232179860b2SJed Brown <para>A user could of course perform all tests in the object's <methodname>configure</methodname> method, but the base 233179860b2SJed Brownclass provides useful logging support for this purpose. Consider again the BLAS example, which will now become, 234179860b2SJed Brown<programlisting> 235179860b2SJed Brown def checkDot(self): 236179860b2SJed Brown '''Verify that the ddot() function is contained in the BLAS library''' 237179860b2SJed Brown return self.libraries.check('libblas.a', 'ddot', otherLibs = self.compilers.flibs, 238179860b2SJed Brown fortranMangle = 1) 239179860b2SJed Brown 240179860b2SJed Brown def configure(self): 241179860b2SJed Brown self.executeTest(self.checkDot) 242179860b2SJed Brown return 243179860b2SJed Brown</programlisting> 244179860b2SJed BrownPassing our test module to the framework, 245179860b2SJed Brown<screen> 246179860b2SJed Brown<prompt>docs$</prompt> <command>PYTHONPATH=`pwd` ../config/framework.py --configModules=[examples.blasTest]</command> 247179860b2SJed Brown</screen> 248179860b2SJed Brownwe produce the following log output in <filename>configure.log</filename>. Notice that it not only records the method and module, but the method doc string, 249179860b2SJed Brownall shell calls, and any output actions as well.</para> 250179860b2SJed Brown<screen> 251179860b2SJed Brown<computeroutput> 252179860b2SJed Brown================================================================================ 253179860b2SJed BrownTEST checkDot from examples.blasTest(/PETSc3/sidl/BuildSystem/docs/examples/blasTest.py:10) 254179860b2SJed BrownTESTING: checkDot from examples.blasTest(/PETSc3/sidl/BuildSystem/docs/examples/blasTest.py:10) 255179860b2SJed Brown Verify that the ddot() function is contained in the BLAS library 256179860b2SJed Brown Checking for functions ['ddot'] in library ['libblas.a'] ['-lfrtbegin', '-lg2c', '-lm', 257179860b2SJed Brown '-L/usr/lib/gcc-lib/i486-linux/3.3.5', '-L/usr/lib/gcc-lib/i486-linux/3.3.5/../../..', 258179860b2SJed Brown '-lm', '-lgcc_s'] 259179860b2SJed Brownsh: gcc -c -o conftest.o -fPIC conftest.c 260179860b2SJed BrownExecuting: gcc -c -o conftest.o -fPIC conftest.c 261179860b2SJed Brownsh: 262179860b2SJed Brownsh: gcc -o conftest -fPIC conftest.o -lblas -lfrtbegin -lg2c -lm 263179860b2SJed Brown -L/usr/lib/gcc-lib/i486-linux/3.3.5 -L/usr/lib/gcc-lib/i486-linux/3.3.5/../../.. -lm -lgcc_s 264179860b2SJed BrownExecuting: gcc -o conftest -fPIC conftest.o -lblas -lfrtbegin -lg2c -lm 265179860b2SJed Brown -L/usr/lib/gcc-lib/i486-linux/3.3.5 -L/usr/lib/gcc-lib/i486-linux/3.3.5/../../.. -lm -lgcc_s 266179860b2SJed Brownsh: 267179860b2SJed BrownDefined HAVE_LIBBLAS to 1 in config.libraries 268179860b2SJed Brown</computeroutput> 269179860b2SJed Brown</screen> 270179860b2SJed Brown 271179860b2SJed Brown </sect2> 272179860b2SJed Brown 273179860b2SJed Brown <sect2 id="Checking-for-headers"> 274179860b2SJed Brown <title>Checking for headers</title> 275179860b2SJed Brown 276179860b2SJed Brown <para>Often, we would like to test for the presence of certain headers. This is done is a completely analogous way to 277179860b2SJed Brownthe library case, using instead the <classname>config.headers</classname> module. Below, we test for the presence of the 278179860b2SJed Brown<command>curses</command> header. 279179860b2SJed Brown<programlisting> 280179860b2SJed Brownimport config.base 281179860b2SJed Brown 282179860b2SJed Brownclass Configure(config.base.Configure): 283179860b2SJed Brown def __init__(self, framework): 284179860b2SJed Brown config.base.Configure.__init__(self, framework) 285179860b2SJed Brown self.headers = self.framework.require('config.headers, self) 286179860b2SJed Brown return 287179860b2SJed Brown 288179860b2SJed Brown def checkCurses(self): 289179860b2SJed Brown 'Verify that we have the curses header' 290179860b2SJed Brown return self.headers.check('curses.h') 291179860b2SJed Brown 292179860b2SJed Brown def configure(self): 293179860b2SJed Brown self.executeTest(self.checkCurses) 294179860b2SJed Brown return 295179860b2SJed Brown</programlisting> 296179860b2SJed BrownRunning this test 297179860b2SJed Brown<screen> 298179860b2SJed Brown<prompt>docs$</prompt> <command>PYTHONPATH=`pwd` ../config/framework.py --configModules=[examples.cursesTest]</command> 299179860b2SJed Brown</screen> 300179860b2SJed Brownproduces the following log output.</para> 301179860b2SJed Brown<screen> 302179860b2SJed Brown<computeroutput> 303179860b2SJed Brown================================================================================ 304179860b2SJed BrownTEST checkCurses from examples.cursesTest(/PETSc3/sidl/BuildSystem/docs/examples/cursesTest.py:9) 305179860b2SJed BrownTESTING: checkCurses from examples.cursesTest(/PETSc3/sidl/BuildSystem/docs/examples/cursesTest.py:9) 306179860b2SJed Brown Verify that we have the curses header 307179860b2SJed BrownChecking for header: curses.h 308179860b2SJed Brownsh: gcc -E conftest.c 309179860b2SJed BrownExecuting: gcc -E conftest.c 310179860b2SJed Brownsh: # 1 "conftest.c" 311179860b2SJed Brown# 1 "<built-in>" 312179860b2SJed Brown# 1 "<command line>" 313179860b2SJed Brown# 1 "conftest.c" 314179860b2SJed Brown# 1 "confdefs.h" 1 315179860b2SJed Brown# 2 "conftest.c" 2 316179860b2SJed Brown# 1 "conffix.h" 1 317179860b2SJed Brown# 3 "conftest.c" 2 318179860b2SJed Brown# 1 "/usr/include/curses.h" 1 3 4 319179860b2SJed Brown# 58 "/usr/include/curses.h" 3 4 320179860b2SJed Brown# 1 "/usr/include/ncurses_dll.h" 1 3 4 321179860b2SJed Brown# 59 "/usr/include/curses.h" 2 3 4 322179860b2SJed Brown# 99 "/usr/include/curses.h" 3 4 323179860b2SJed Browntypedef unsigned long chtype; 324179860b2SJed Brown# 1 "/usr/include/stdio.h" 1 3 4 325179860b2SJed Brown# 28 "/usr/include/stdio.h" 3 4 326179860b2SJed Brown# 1 "/usr/include/features.h" 1 3 4 327179860b2SJed Brown# 295 "/usr/include/features.h" 3 4 328179860b2SJed Brown# 1 "/usr/include/sys/cdefs.h" 1 3 4 329179860b2SJed Brown# 296 "/usr/include/features.h" 2 3 4 330179860b2SJed Brown# 318 "/usr/include/features.h" 3 4 331179860b2SJed Brown#... 332179860b2SJed Brown... W* win,int* y, int* x, _Bool to_screen); 333179860b2SJed Brownextern _Bool mouse_trafo (int*, int*, _Bool); 334179860b2SJed Brownextern int mcprint (char *, int); 335179860b2SJed Brownextern int has_key (int); 336179860b2SJed Brownextern void _tracef (const char *, ...) ; 337179860b2SJed Brownextern void _tracedump (const char *, WINDOW *); 338179860b2SJed Brownextern char * _traceattr (attr_t); 339179860b2SJed Brownextern char * _traceattr2 (int, chtype); 340179860b2SJed Brownextern char * _nc_tracebits (void); 341179860b2SJed Brownextern char * _tracechar (int); 342179860b2SJed Brownextern char * _tracechtype (chtype); 343179860b2SJed Brownextern char * _tracechtype2 (int, chtype); 344179860b2SJed Brown# 1203 "/usr/include/curses.h" 3 4 345179860b2SJed Brownextern char * _tracemouse (const MEVENT *); 346179860b2SJed Brownextern void trace (const unsigned int); 347179860b2SJed Brown# 4 "conftest.c" 2 348179860b2SJed Brown 349179860b2SJed BrownDefined HAVE_CURSES_H to 1 in config.headers 350179860b2SJed Brown</computeroutput> 351179860b2SJed Brown</screen> 352179860b2SJed Brown 353179860b2SJed Brown<para>Alternatively, we could have specified that this header be included in the list of header files checked by default.</para> 354179860b2SJed Brown<programlisting> 355179860b2SJed Brownimport config.base 356179860b2SJed Brown 357179860b2SJed Brownclass Configure(config.base.Configure): 358179860b2SJed Brown def __init__(self, framework): 359179860b2SJed Brown config.base.Configure.__init__(self, framework) 360179860b2SJed Brown self.headers = self.framework.require('config.headers, self) 361179860b2SJed Brown self.headers.headers.append('curses.h') 362179860b2SJed Brown return 363179860b2SJed Brown 364179860b2SJed Brown def checkCurses(self): 365179860b2SJed Brown 'Verify that we have the curses header' 366179860b2SJed Brown return self.headers.haveHeader('curses.h') 367179860b2SJed Brown 368179860b2SJed Brown def configure(self): 369179860b2SJed Brown self.executeTest(self.checkCurses) 370179860b2SJed Brown return 371179860b2SJed Brown</programlisting> 372179860b2SJed Brown 373179860b2SJed Brown<para>In addition, the base class does include lower level support for preprocessing files. The 374179860b2SJed Brown<methodname>preprocess</methodname> method takes a code string as input and return a tuple of the 375179860b2SJed Brown<command>(stdout,stderr,error code)</command> for the run. The <methodname>outputPreprocess</methodname> method returns 376179860b2SJed Brownonly the standard output, and <methodname>checkPreprocess</methodname> returns true if no error occurs.</para> 377179860b2SJed Brown 378179860b2SJed Brown </sect2> 379179860b2SJed Brown 380179860b2SJed Brown <sect2 id="Checking-for-libraries"> 381179860b2SJed Brown <title>Checking for libraries</title> 382179860b2SJed Brown 383179860b2SJed Brown <para>We have already demonstrated a test for the existence of a function in a library. However the 384179860b2SJed Brown<methodname>check</methodname> method is much more general. It allows the specification of multiple libraries and 385179860b2SJed Brownmultiple functions, as well as auxiliary libraries. For instance, to check for the <methodname>MPI_Init</methodname> and 386179860b2SJed Brown<methodname>MPI_Comm_create</methodname> functions in MPICH when the Fortran bindings are active, we would use: 387179860b2SJed Brown<programlisting> 388179860b2SJed Brown self.libraries.check(['libmpich.so', 'libpmpich.so'], ['MPI_Init', 'MPI_Comm_create'], 389179860b2SJed Brown otherLibs = self.compilers.flibs) 390179860b2SJed Brown</programlisting> 391179860b2SJed BrownAs in the BLAS example, we can also turn on Fortran name mangling. The caller may also supply a function prototype and 392179860b2SJed Browncalling sequence, which are necessary if the current language is C++. 393179860b2SJed Brown</para> 394179860b2SJed Brown 395179860b2SJed Brown<para>It is also necessary at some times to determine whether a given library is a shared object. This can be 396179860b2SJed Brownaccomplished using the <methodname>checkShared</methodname> method, as we demonstrate with the MPICH library in a call 397179860b2SJed Browntaken from the MPI configure module in PETSc. 398179860b2SJed Brown<programlisting> 399179860b2SJed Brown self.libraries.checkShared('#include <mpi.h>\n', 'MPI_Init', 'MPI_Initialized', 400179860b2SJed Brown 'MPI_Finalize', checkLink = self.checkMPILink, 401179860b2SJed Brown libraries = self.lib) 402179860b2SJed Brown</programlisting> 403179860b2SJed BrownThe theory for the check is that a shared object will have only one copy of any global variable. Thus functions such as 404179860b2SJed Brown<methodname>MPI_Initialized</methodname> will render consistent results across other libraries. The test begins by 405179860b2SJed Browncreating two dynamic libraries, both of which link the given library. Then an executable is constructed which loads the 406179860b2SJed Brownlibraries in turn. The first library calls the initizlization functions, here <methodname>MPI_Init</methodname>, and the 407179860b2SJed Brownsecond library calls the initialization check function, here <methodname>MPI_Initialized</methodname>. The check 408179860b2SJed Brownfunction will return true if the given library is a shared object. This organization is shown in figure ???</para> 409179860b2SJed Brown<para> 410179860b2SJed Brown<inlinemediaobject> 411179860b2SJed Brown<imageobject><imagedata fileref="sharedLibraryCheck" format="EPS"/></imageobject> 412179860b2SJed Brown<imageobject><imagedata fileref="sharedLibraryCheck" format="JPG"/></imageobject> 413179860b2SJed Brown<!-- <textobject><phrase>A diagram of the link structure for the shared library test</phrase></textobject> --> 414179860b2SJed Brown</inlinemediaobject> 415179860b2SJed Brown</para> 416179860b2SJed Brown 417179860b2SJed Brown <para>The lower level interface to compiling and linking in the base class mirrors that for preprocessing. The 418179860b2SJed Brown<methodname>outputCompile</methodname> and <methodname>checkCompile</methodname> methods function in the same way. The 419179860b2SJed Browncode is now broken up into four distinct sections. There are includes, the body of <methodname>main</methodname>, and a 420179860b2SJed Brownpossible replacement for the beginning and end of the <methodname>main</methodname> declaration. The linking methods, 421179860b2SJed Brown<methodname>outputLink</methodname> and <methodname>checkLink</methodname>, are exactly analogous.</para> 422179860b2SJed Brown 423179860b2SJed Brown <para>There are also some convenience methods provided to handle compiler and linker flags. The 424179860b2SJed Brown<methodname>checkCompilerFlag</methodname> and <methodname>checkLinkerFlag</methodname> try to determine whether a given 425179860b2SJed Brownflag is accepted by the processor, while <methodname>addCompilerFlag</methodname> and 426179860b2SJed Brown<methodname>addLinkerFlag</methodname> will do that check and add any valid flag to the list of default flags.</para> 427179860b2SJed Brown 428179860b2SJed Brown </sect2> 429179860b2SJed Brown 430179860b2SJed Brown <sect2 id="Checking-for-executables"> 431179860b2SJed Brown <title>Checking for executables</title> 432179860b2SJed Brown 433179860b2SJed Brown <para>The <methodname>getExecutable</methodname> method is used to locate executable files. For instance, this code 434179860b2SJed Brownwould allow us to locate the <command>valgrind</command> binary. 435179860b2SJed Brown<programlisting> 436179860b2SJed Brown self.getExecutable('valgrind') 437179860b2SJed Brown</programlisting> 438179860b2SJed BrownIf the program is found, a member variable of the same name will be set in the object to the program name, and a make 439179860b2SJed Brownmacro defined to it as well. We can opt for these to contain the full path by using the <option>getFullPath</option> 440179860b2SJed Brownargument. In addition, we can change the name of the member variable and macro using the <option>resultName</option> 441179860b2SJed Brownargument. 442179860b2SJed Brown</para> 443179860b2SJed Brown 444179860b2SJed Brown<para>We also have control over the search path used. If we give no arguments, the default path from the environment is 445179860b2SJed Brownused. This can be overridden with a new path using the <option>path</option> argument, either as a Python list or a 446179860b2SJed Browncolon separated string. Furthermore, the default path can be added to this custom path using the 447179860b2SJed Brown<option>useDefaultPath</option> argument. For instance, this call 448179860b2SJed Brown<programlisting> 449179860b2SJed Brown self.getExecutable('valgrind', path=['/opt/valgrind-1.0'], getFullPath=1, 450179860b2SJed Brown useDefaultPath=1, resultName='grinder') 451179860b2SJed Brown</programlisting> 452179860b2SJed Brownwill check for <command>valgrind</command> first in <filename>/opt/valgrind-1.0</filename> and then along the default 453179860b2SJed Brownpath. If found in the first location, it will set <varname>self.grinder</varname> to 454179860b2SJed Brown<filename>/opt/valgrind-1.0/valgrind</filename> as well as define <envar>GRINDER</envar> to the same value in makefiles. 455179860b2SJed Brown</para> 456179860b2SJed Brown 457179860b2SJed Brown <para>As in the cases of preprocessing, compiling, and linking, the lower level operations are also exposed. The 458179860b2SJed Brown<methodname>checkRun</methodname> method takes in a code string and returns true if the executable runs without 459179860b2SJed Brownerror. The <methodname>outputRun</methodname> method returns the output and status code. Both methods us the safe 460179860b2SJed Brownexecution routine <methodname>config.base.Configure.executeShellCommand</methodname> which accepts a timeout. Moreover, 461179860b2SJed Brownthere commands can run in the special batch mode described in section ???.</para> 462179860b2SJed Brown 463179860b2SJed Brown </sect2> 464179860b2SJed Brown 465179860b2SJed Brown <sect2 id="Output-results"> 466179860b2SJed Brown <title>Output results</title> 467179860b2SJed Brown 468179860b2SJed Brown <para>The BuildSystem configure includes the traditional output methods employed by <command>autoconf</command> to 469179860b2SJed Brownenable communication with <command>make</command>. Individual configure modules use the 470179860b2SJed Brown<methodname>addDefine</methodname> method to add C <methodname>#define</methodname> statements to a configuration header 471179860b2SJed Brownand the <methodname>addSubstitution</methodname> to setup substitution rules for specified files. For instance, to 47215ac2963SJed Brownactivate the parmetis package, we might provide 473179860b2SJed Brown<programlisting> 474179860b2SJed Brown self.addDefine('HAVE_PARMETIS', 1) 475179860b2SJed Brown</programlisting> 476179860b2SJed Brownand then for the make process 477179860b2SJed Brown<programlisting> 478179860b2SJed Brown self.addSubstitution('PARMETIS_INCLUDE', ' '.join([self.libraries.getIncludeArgument(i) 479179860b2SJed Brown for i in self.include])) 480179860b2SJed Brown self.addSubstitution('PARMETIS_LIB, ' '.join([self.libraries.getLibArgument(l) 481179860b2SJed Brown for l in self.lib])) 482179860b2SJed Brown</programlisting> 483179860b2SJed Brown</para> 484179860b2SJed Brown 485179860b2SJed Brown<para>The actual output of this data is controlled by the framework. The user specifies the header file using the 486179860b2SJed Brown<varname>header</varname> field of the framework, and then the file is created automatically during the configure 487179860b2SJed Brownprocess, but can be output at any time using the <methodname>outputHeader</methodname> method. Furthermore, the 488179860b2SJed Brown<methodname>addSubstitutionFile</methodname> method can be used to tag a file for substitution, and also specify a 489179860b2SJed Browndifferent file for the result of the substitution.</para> 490179860b2SJed Brown 491179860b2SJed Brown<para>In the <command>autoconf</command> approach, separating the the defines and substitutions for different packages 492179860b2SJed Brownbecomes troublesome, and in some cases impossible to maintain. To help with this, we have introduced 493179860b2SJed Brown<emphasis>prefixes</emphasis> for the defines and substitutions. The are strings, unique to each module, which are 494179860b2SJed Brownprepended with an underscore to each identifier defined or substituted. These are set on a per object basis using the 495179860b2SJed Brown<varname>headerPrefix</varname> and <varname>substPrefix</varname> members. For instance, in our 49615ac2963SJed Brownparmetis example, if we instead used the code 497179860b2SJed Brown<programlisting> 498179860b2SJed Brown self.headerPrefix = 'MATT' 499179860b2SJed Brown self.addDefine('HAVE_PARMETIS', 1) 500179860b2SJed Brown</programlisting> 501179860b2SJed Brownin our configuration header we would see 502179860b2SJed Brown<programlisting> 503179860b2SJed Brown #ifndef MATT_HAVE_PARMETIS 504179860b2SJed Brown #define MATT_HAVE_PARMETIS 1 505179860b2SJed Brown #endif 506179860b2SJed Brown</programlisting> 507179860b2SJed BrownNote that the value of the prefix is used at output time, not at the time that the define or substitution is set. 508179860b2SJed Brown</para> 509179860b2SJed Brown 510179860b2SJed Brown<para>Another extension of the old-style output mechanisms adds more C structure to the interface. The 511179860b2SJed Brown<methodname>addTypedef</methodname> method allows a typedef from one typename to another, which in 512179860b2SJed Brown<command>autoconf</command> is handled by a define. Likewise <methodname>addPrototype</methodname> can add a missing 513179860b2SJed Brownfunction prototype to a header. Since these are C specific structures, they are output into a separate configuration 514179860b2SJed Brownheader file, which is controlled by the <varname>cHeader</varname> member variable.</para> 515179860b2SJed Brown 516179860b2SJed Brown<para>Extending in a different direction, we allow makefile structures to be specified directly rather than through 517179860b2SJed Brownsubstitutions. Using <methodname>addMakeMacro</methodname>, we can add variable definitions to the configuration 518179860b2SJed Brownmakefile, whereas <methodname>addMakeRule</methodname> allows the user to specify a make target, complete with 51915ac2963SJed Browndependencies and action. As an example, we will replace our parmetis example from above with the following code 520179860b2SJed Brown<programlisting> 521179860b2SJed Brown self.addMakeMacro('PARMETIS_INCLUDE', ' '.join([self.libraries.getIncludeArgument(i) 522179860b2SJed Brown for i in self.include])) 523179860b2SJed Brown self.addMakeMacro('PARMETIS_LIB, ' '.join([self.libraries.getLibArgument(l) 524179860b2SJed Brown for l in self.lib])) 525179860b2SJed Brown self.addMakeRule('.c.o', '', ['${CC} -c -o $@ -I${PARMETIS_INCLUDE} $<']) 526179860b2SJed Brown self.addMakeRule('myApp', '${.c=.o:SOURCE}', ['${CC} -o $@ $< ${PARMETIS_LIB}']) 527179860b2SJed Brown</programlisting> 528179860b2SJed Brownwhich will produce 529179860b2SJed Brown<programlisting> 53015ac2963SJed Brown PARMETIS_INCLUDE = -I/home/knepley/petsc-dev/externalpackages/parmetis/build/Darwin-x86_64/include 53115ac2963SJed Brown PARMETIS_LIB = -L/home/knepley/petsc-dev/externalpackages/parmetis/build/Darwin-x86_64/lib -lparmetis -lmetis 532179860b2SJed Brown</programlisting> 533179860b2SJed Brownin the file specified by the <varname>makeMacroHeader</varname> member variable, and 534179860b2SJed Brown<programlisting> 535179860b2SJed Brown myApp: ${.c=.o:SOURCE} 536179860b2SJed Brown ${CC} -i $@ $< ${PARMETIS_LIB} 537179860b2SJed Brown</programlisting> 538179860b2SJed Brownin the file specified by the <varname>makeRuleHeader</varname> member variable.</para> 539179860b2SJed Brown 540179860b2SJed Brown<para>The above output methods are all specified on a per configure object basis, however this may become confusing in a 541179860b2SJed Brownlarge project. All the prefixes and output filenames would have to be coordinated. A common strategy is to use the 542179860b2SJed Brownframework for coordination, putting all the output into the framework object itself. For instance, we might have 543179860b2SJed Brown<programlisting> 544179860b2SJed Brown self.framework.addDefine('HAVE_PARMETIS', 1) 545179860b2SJed Brown</programlisting> 546179860b2SJed Brownwhich would allow the define to appear in the headre specified by the framework with the framework prefix. 547179860b2SJed Brown</para> 548179860b2SJed Brown 549179860b2SJed Brown </sect2> 550179860b2SJed Brown 551179860b2SJed Brown</sect1> 552179860b2SJed Brown 553179860b2SJed Brown<sect1 id="Configuring-batch-systems"> 554179860b2SJed Brown<title>Configuring batch systems</title> 555179860b2SJed Brown 556179860b2SJed Brown<para>It is not uncommon for large clusters or supercomputing centers to have a batch execution policy, making it 557179860b2SJed Browndifficult for configure to execute the few tests that depend on executing code, rather than compiling and linking it. To 558179860b2SJed Brownhandle this case, we provide the <option>--with-batch</option> argument. The code to be run is collected in a single 559179860b2SJed Brownexecutable which the user must submit to the system. This executable produces a <emphasis>reconfigure</emphasis> script 560179860b2SJed Brownwhich may then be run to fully configure the system.</para> 561179860b2SJed Brown 562179860b2SJed Brown<para>When configure is run with the <option>--with-batch</option> option, the following message will appear. 563179860b2SJed Brown<screen> 564179860b2SJed Brown<prompt>petsc-dev$</prompt> <command>./config/configure.py --with-batch</command> 565179860b2SJed Brown</screen> 566179860b2SJed Brownproduces the following log output. 567179860b2SJed Brown<screen> 568179860b2SJed Brown<computeroutput> 569179860b2SJed Brown================================================================================= 570179860b2SJed Brown Since your compute nodes require use of a batch system or mpirun you must: 571179860b2SJed Brown 1) Submit ./conftest to your batch system (this will generate the file reconfigure) 572179860b2SJed Brown 2) Run "python reconfigure" (to complete the configure process). 573179860b2SJed Brown================================================================================= 574179860b2SJed Brown</computeroutput> 575179860b2SJed Brown</screen> 576179860b2SJed BrownThe user must then execute the <filename>conftest</filename> binary, and then run the <command>python 577179860b2SJed Brownreconfigure</command> command. 578179860b2SJed Brown</para> 579179860b2SJed Brown 580179860b2SJed Brown<para>If a user defined test relies upon running code, he may make it suitable for a batch system. The 581179860b2SJed Brown<methodname>checkRun</methodname> method takes the <option>defaultArg</option> argument which names a configure option 582179860b2SJed Brownwhose value may substitute for the outcome of the test, allowing a user to preempt the run. For instance, the 583179860b2SJed Brown<methodname>config.types.checkEndian</methodname> method contains the code 584179860b2SJed Brown<programlisting> 585179860b2SJed Brown if self.checkRun('', body, defaultArg = 'isLittleEndian'): 586179860b2SJed Brown</programlisting> 587179860b2SJed Brownwhich means the <option>isLittleEndian</option> option can be given to replace the output of the run. However, this does 588179860b2SJed Brownthe require the user to supply the missing option.</para> 589179860b2SJed Brown 590179860b2SJed Brown<para>To automate this process, the test should first check for batch mode. Using the 591179860b2SJed Brown<methodname>addBatchInclude</methodname> and <methodname>addBatchBody</methodname> methods, code can be included in the 592179860b2SJed Brownbatch executable. We return to the endian test to illustrate this usage. 593179860b2SJed Brown<programlisting> 594179860b2SJed Brown if not self.framework.argDB['with-batch']: 595179860b2SJed Brown body = ''' 596179860b2SJed Brown /* Are we little or big endian? From Harbison & Steele. */ 597179860b2SJed Brown union 598179860b2SJed Brown { 599179860b2SJed Brown long l; 600179860b2SJed Brown char c[sizeof(long)]; 601179860b2SJed Brown } u; 602179860b2SJed Brown u.l = 1; 603179860b2SJed Brown exit(u.c[sizeof(long) - 1] == 1); 604179860b2SJed Brown ''' 605179860b2SJed Brown if self.checkRun('', body, defaultArg = 'isLittleEndian'): 606179860b2SJed Brown endian = 'little' 607179860b2SJed Brown else: 608179860b2SJed Brown endian = 'big' 609179860b2SJed Brown else: 610179860b2SJed Brown self.framework.addBatchBody( 611179860b2SJed Brown ['{', 612179860b2SJed Brown ' union {long l; char c[sizeof(long)];} u;', 613179860b2SJed Brown ' u.l = 1;', 614179860b2SJed Brown ' fprintf(output, " \'--with-endian=%s\',\\n",\ 615179860b2SJed Brown (u.c[sizeof(long) - 1] == 1) ? "little" : "big");', 616179860b2SJed Brown '}']) 617179860b2SJed Brown # Dummy value 618179860b2SJed Brown endian = 'little' 619179860b2SJed Brown</programlisting> 620179860b2SJed BrownThe batch body code should output configure options to the <varname>output</varname> file descriptor. These are 621179860b2SJed Browncollected for the new configure run in the <filename>reconfigure</filename> script. 622179860b2SJed Brown</para> 623179860b2SJed Brown 624179860b2SJed Brown</sect1> 625179860b2SJed Brown 626179860b2SJed Brown</chapter> 627179860b2SJed Brown 628179860b2SJed Brown<chapter id="Build"> 629179860b2SJed Brown<title>Build</title> 630179860b2SJed Brown 631179860b2SJed Brown<para>The build operation now encompasses the configure, compile, link, install, and update operations.</para> 632179860b2SJed Brown 633179860b2SJed Brown<sect1 id="Running-make"> 634179860b2SJed Brown<title>Running make</title> 635179860b2SJed Brown 636179860b2SJed Brown<para>All options for both configuration and build are given to <filename>make.py</filename>. Thus, the simplest build 637179860b2SJed Brownis merely 638179860b2SJed Brown<screen> 639179860b2SJed Brown<prompt>petsc-dev$</prompt> <command>./make.py</command> 640179860b2SJed Brown</screen> 641179860b2SJed BrownThe help is also given by <option>-help</option>, but this time it will also include build switches. 642179860b2SJed Brown<screen> 643179860b2SJed Brown<prompt>petsc-dev$</prompt> <command>./make.py -help</command> 644179860b2SJed Brown<computeroutput> 645179860b2SJed BrownScript Help 646179860b2SJed Brown----------- 647179860b2SJed BrownScript: 648179860b2SJed Brown --help : Print this help message current: 1 649179860b2SJed Brown --h : Print this help message current: 0 650179860b2SJed BrownMake: 651179860b2SJed Brown -forceConfigure : Force a reconfiguration current: 0 652179860b2SJed Brown -ignoreCompileOutput : Ignore compiler output current: 1 653179860b2SJed Brown -defaultRoot : Directory root for all packages current: ../.. 654179860b2SJed Brown -prefix : Root for installation of libraries and binaries 655179860b2SJed BrownSIDLMake: 656179860b2SJed Brown -bootstrap : Generate the boostrap client current: 0 657179860b2SJed Brown -outputSIDLFiles : Write generated files to disk current: 1 658179860b2SJed Brown -excludeLanguages=<languages> : Do not load configurations from RDict for the given languages current: [] 659179860b2SJed Brown -excludeBasenames=<names> : Do not load configurations from RDict for these SIDL base names current: [] 660179860b2SJed Brown</computeroutput> 661179860b2SJed Brown</screen> 662179860b2SJed Brown</para> 663179860b2SJed Brown 664179860b2SJed Brown</sect1> 665179860b2SJed Brown 666179860b2SJed Brown<sect1 id="Makers"> 667179860b2SJed Brown<title>Makers</title> 668179860b2SJed Brown 669179860b2SJed Brown<para>The build operation now encompasses configure, compile, and link operations, which are coordinated by objects of 670179860b2SJed Brownclass <classname>maker.Maker</classname>. This object manages: 671179860b2SJed Brown<itemizedlist> 672179860b2SJed Brown <listitem><para>configuration,</para></listitem> 673179860b2SJed Brown <listitem><para>build,</para></listitem> 674179860b2SJed Brown <listitem><para>install, and</para></listitem> 675179860b2SJed Brown <listitem><para>project dependencies</para></listitem> 676179860b2SJed Brown</itemizedlist> 677179860b2SJed BrownAll options, no matter which component they are intended for, are given uniformly to <filename>make.py</filename>. 678179860b2SJed Brown</para> 679179860b2SJed Brown 680179860b2SJed Brown <sect2 id="SIDLMaker"> 681179860b2SJed Brown <title>SIDLMaker</title> 682179860b2SJed Brown 683179860b2SJed Brown<para>This is a subclass which handles source generation from SIDL.</para> 684179860b2SJed Brown 685179860b2SJed Brown </sect2> 686179860b2SJed Brown 687179860b2SJed Brown</sect1> 688179860b2SJed Brown 689179860b2SJed Brown<sect1 id="Builders"> 690179860b2SJed Brown<title>Builders</title> 691179860b2SJed Brown 692179860b2SJed Brown<para>The build operation now encompasses the configure, compile, and link operations.</para> 693179860b2SJed Brown 694179860b2SJed Brown</sect1> 695179860b2SJed Brown 696179860b2SJed Brown<sect1 id="LanguageProcessors"> 697179860b2SJed Brown<title>LanguageProcessors</title> 698179860b2SJed Brown 699179860b2SJed Brown<para>The build operation now encompasses the configure, compile, and link operations.</para> 700179860b2SJed Brown 701179860b2SJed Brown</sect1> 702179860b2SJed Brown 703179860b2SJed Brown<sect1 id="Interaction-with-Configure"> 704179860b2SJed Brown<title>Interaction with Configure</title> 705179860b2SJed Brown 706179860b2SJed Brown<para>The pickled configure is loaded by Maker, and then the config.compile objects are jacked into the Builder.</para> 707179860b2SJed Brown 708179860b2SJed Brown</sect1> 709179860b2SJed Brown 710179860b2SJed Brown</chapter> 711179860b2SJed Brown 712179860b2SJed Brown</book> 713