1*4bcd95a3SBarry Smith(ch_buildsystem)= 2*4bcd95a3SBarry Smith 3*4bcd95a3SBarry Smith# BuildSystem 4*4bcd95a3SBarry Smith 5*4bcd95a3SBarry Smith`BuildSystem` (located in `config/BuildSystem`) configures PETSc before PETSc is compiled with make. 6*4bcd95a3SBarry SmithIt is much like [GNU Autoconf (configure)](https://www.gnu.org/savannah-checkouts/gnu/autoconf/manual/autoconf-2.71/html_node/index.html#Top) 7*4bcd95a3SBarry Smithbut written in Python especially for PETSc. 8*4bcd95a3SBarry Smith 9*4bcd95a3SBarry Smith## What is a build? 10*4bcd95a3SBarry Smith 11*4bcd95a3SBarry SmithThe build stage compiles source to object files, stores them 12*4bcd95a3SBarry Smith(usually in archives), and links shared libraries and executables. These 13*4bcd95a3SBarry Smithare mechanical operations that reduce to applying a construction rule to 14*4bcd95a3SBarry Smithsets of files. The [Make](http://www.gnu.org/software/make/) tool is 15*4bcd95a3SBarry Smithgreat at this job. 16*4bcd95a3SBarry Smith 17*4bcd95a3SBarry Smith## Why is configure necessary? 18*4bcd95a3SBarry Smith 19*4bcd95a3SBarry SmithThe `configure` program is designed to assemble all information and preconditions 20*4bcd95a3SBarry Smithnecessary for the build stage. This is a far more complicated task, heavily dependent on 21*4bcd95a3SBarry Smiththe local hardware and software environment. It is also the source of nearly every build 22*4bcd95a3SBarry Smithproblem. The most crucial aspect of a configure system is not performance, scalability, or 23*4bcd95a3SBarry Smitheven functionality, but *debuggability*. Configuration failure is at least as common as 24*4bcd95a3SBarry Smithsuccess, due to broken tools, operating system upgrades, hardware incompatibilities, user 25*4bcd95a3SBarry Smitherror, and a host of other reasons. Problem diagnosis is the single biggest bottleneck for 26*4bcd95a3SBarry Smithdevelopment and maintenance time. Unfortunately, current systems are built to optimize the 27*4bcd95a3SBarry Smithsuccessful case rather than the unsuccessful. In PETSc, we have developed the 28*4bcd95a3SBarry Smith`BuildSystem` package to remedy the shortcomings of configuration systems such as 29*4bcd95a3SBarry SmithAutoconf, CMake, and SCons. 30*4bcd95a3SBarry Smith 31*4bcd95a3SBarry Smith## Why use PETSc BuildSystem? 32*4bcd95a3SBarry Smith 33*4bcd95a3SBarry SmithAs several configuration tools 34*4bcd95a3SBarry Smithcurrently exist, it is instructive to consider why PETSc would choose to create another 35*4bcd95a3SBarry Smithfrom scratch. Below we list features and design considerations which lead us to prefer 36*4bcd95a3SBarry Smith`BuildSystem` to the alternatives. 37*4bcd95a3SBarry Smith 38*4bcd95a3SBarry Smith### Namespacing 39*4bcd95a3SBarry Smith 40*4bcd95a3SBarry Smith`BuildSystem` wraps collections of related tests in Python modules, which also hold 41*4bcd95a3SBarry Smiththe test results. Thus results are accessed using normal Python 42*4bcd95a3SBarry Smithnamespacing. As rudimentary as this sounds, no namespacing beyond the 43*4bcd95a3SBarry Smithuse of variable name prefixes is present in Autoconf, CMake, and SCons. 44*4bcd95a3SBarry SmithInstead, a flat namespace is used. This 45*4bcd95a3SBarry Smithtendency appears again when composing command lines for external tools, 46*4bcd95a3SBarry Smithsuch as the compiler and linker. In the traditional configure tools, 47*4bcd95a3SBarry Smithoptions are aggregated in a single bucket variable, such as `INCLUDE` 48*4bcd95a3SBarry Smithor `LIBS`, whereas in `BuildSystem` one can trace the provenance of a flag before it 49*4bcd95a3SBarry Smithis added to the command line. CMake also makes the unfortunate decision 50*4bcd95a3SBarry Smithto force all link options to resolve to full paths, which causes havoc 51*4bcd95a3SBarry Smithwith compiler-private libraries. 52*4bcd95a3SBarry Smith 53*4bcd95a3SBarry Smith### Explicit control flow 54*4bcd95a3SBarry Smith 55*4bcd95a3SBarry SmithThe `BuildSystem` configure modules mentioned above, containing one `Configure` object 56*4bcd95a3SBarry Smithper module, are organized explicitly into a directed acyclic graph 57*4bcd95a3SBarry Smith(DAG). The user indicates dependence, an *edge* in the dependence graph, 58*4bcd95a3SBarry Smithwith a single call, `requires('path.to.other.test', self)`, which not 59*4bcd95a3SBarry Smithonly structures the DAG, but returns the `Configure` object. The caller 60*4bcd95a3SBarry Smithcan then use this object to access the results of the tests run by the 61*4bcd95a3SBarry Smithdependency, achieving test and result encapsulation simply. 62*4bcd95a3SBarry Smith 63*4bcd95a3SBarry Smith### Multi-language tests 64*4bcd95a3SBarry Smith 65*4bcd95a3SBarry Smith`BuildSystem` maintains an explicit language stack, so that the current language 66*4bcd95a3SBarry Smithcan be manipulated by the test environment. A compile or link can be run 67*4bcd95a3SBarry Smithusing any language, complete with the proper compilers, flags, 68*4bcd95a3SBarry Smithlibraries, etc., with a single call. This automation is crucial 69*4bcd95a3SBarry Smithfor cross-language tests, which are thinly supported in current 70*4bcd95a3SBarry Smithtools. In fact, the design of these tools inhibits this kind of check. 71*4bcd95a3SBarry SmithThe `check_function_exists()` call in Autoconf and CMake looks only 72*4bcd95a3SBarry Smithfor the presence of a particular symbol in a library, and fails in C++ 73*4bcd95a3SBarry Smithand on Microsoft Windows, whereas the equivalent `BuildSystem` test can also take a 74*4bcd95a3SBarry Smithdeclaration. The `try_compile()` test in Autoconf and CMake requires 75*4bcd95a3SBarry Smiththe entire list of libraries be present in the `LIBS` variable, 76*4bcd95a3SBarry Smithproviding no good way to obtain libraries from other tests in a modular 77*4bcd95a3SBarry Smithfashion. As another example, if the user has a dependent library that 78*4bcd95a3SBarry Smithrequires `libstdc++`, but they are working with a C project, no 79*4bcd95a3SBarry Smithstraightforward method exists to add this dependency. 80*4bcd95a3SBarry Smith 81*4bcd95a3SBarry Smith### Subpackages 82*4bcd95a3SBarry Smith 83*4bcd95a3SBarry SmithThe most complicated, yet perhaps most useful, part of `BuildSystem` is 84*4bcd95a3SBarry Smithsupport for dependent packages. It provides an object scaffolding for 85*4bcd95a3SBarry Smithincluding a 3rd party package (more than 100 are now available) so that 86*4bcd95a3SBarry SmithPETSc downloads and builds the package for use by PETSc. The native 87*4bcd95a3SBarry Smithconfigure and build system for the package is used, and special support 88*4bcd95a3SBarry Smithexists for Autoconf and CMake packages. No similar system exists in the other 89*4bcd95a3SBarry Smithtools, which rely on static declarations, such as `pkg-config` or 90*4bcd95a3SBarry Smith`FindPackage.cmake` files, that are not tested and often become 91*4bcd95a3SBarry Smithobsolete. 92*4bcd95a3SBarry Smith 93*4bcd95a3SBarry Smith### Batch environments 94*4bcd95a3SBarry Smith 95*4bcd95a3SBarry SmithMost systems, such as Autoconf and CMake, do not actually run tests in a 96*4bcd95a3SBarry Smithbatch environment, but rather require a direct specification, in CMake a 97*4bcd95a3SBarry Smith"platform file". This requires a human expert to write and maintain the 98*4bcd95a3SBarry Smithplatform file. Alternatively, `BuildSystem` submits a dynamically 99*4bcd95a3SBarry Smithgenerated set of tests to the batch system, enabling automatic 100*4bcd95a3SBarry Smithcross-configuration and cross-compilation. 101*4bcd95a3SBarry Smith 102*4bcd95a3SBarry Smith### Caching 103*4bcd95a3SBarry Smith 104*4bcd95a3SBarry SmithCaching often seems like an attractive option since configuration can be 105*4bcd95a3SBarry Smithquite time-consuming, and both Autoconf and CMake enable caching by 106*4bcd95a3SBarry Smithdefault. However, no system has the ability to reliably invalidate the 107*4bcd95a3SBarry Smithcache when the environment for the configuration changes. For example, a 108*4bcd95a3SBarry Smithcompiler or library dependency may be upgraded on the system. Moreover, 109*4bcd95a3SBarry Smithdependencies between cached variables are not tracked, so that even if 110*4bcd95a3SBarry Smithsome variables are correctly updated after an upgrade, others which 111*4bcd95a3SBarry Smithdepend on them may not be. Moreover, CMake mixes together information 112*4bcd95a3SBarry Smithwhich is discovered automatically with that explicitly provided by the 113*4bcd95a3SBarry Smithuser, which is often not tested. 114*4bcd95a3SBarry Smith 115*4bcd95a3SBarry Smith### Concision 116*4bcd95a3SBarry Smith 117*4bcd95a3SBarry SmithThe cognitive load is usually larger for larger code bases, 118*4bcd95a3SBarry Smithand our observation is that the addition of logic to Autoconf 119*4bcd95a3SBarry Smithand CMake is often quite cumbersome and verbose as they do not employ a modern, 120*4bcd95a3SBarry Smithhigher level language. Although `BuildSystem` itself is not widely used, 121*4bcd95a3SBarry Smithit has the advantage of being written in Python, a widely-understood, high-level 122*4bcd95a3SBarry Smithlanguage. 123*4bcd95a3SBarry Smith 124*4bcd95a3SBarry Smith## High level organization 125*4bcd95a3SBarry Smith 126*4bcd95a3SBarry SmithA minimal `BuildSystem` setup consists of a `config` directory off the 127*4bcd95a3SBarry Smithpackage root, which contains all the Python necessary to run (in addition 128*4bcd95a3SBarry Smithto the `BuildSystem` source). At minimum, the `config` directory contains 129*4bcd95a3SBarry Smith`configure.py`, which is executed to run the configure process, and a 130*4bcd95a3SBarry Smithmodule for the package itself. For example, PETSc contains 131*4bcd95a3SBarry Smith`config/PETSc/petsc.py`. It is also common to include a top level 132*4bcd95a3SBarry Smith`configure` file to execute the configure, as this looks like 133*4bcd95a3SBarry SmithAutotools, 134*4bcd95a3SBarry Smith 135*4bcd95a3SBarry Smith```python 136*4bcd95a3SBarry Smith#!/usr/bin/env python3 137*4bcd95a3SBarry Smithimport os 138*4bcd95a3SBarry Smithexecfile(os.path.join(os.path.dirname(__file__), 'config', 'configure.py')) 139*4bcd95a3SBarry Smith``` 140*4bcd95a3SBarry Smith 141*4bcd95a3SBarry SmithThe `configure.py` script constructs a tree of configure modules and 142*4bcd95a3SBarry Smithexecutes the configure process over it. A minimal version of this would 143*4bcd95a3SBarry Smithbe 144*4bcd95a3SBarry Smith 145*4bcd95a3SBarry Smith```python 146*4bcd95a3SBarry Smithpackage = 'PETSc' 147*4bcd95a3SBarry Smith 148*4bcd95a3SBarry Smithdef configure(configure_options): 149*4bcd95a3SBarry Smith # Command line arguments take precedence (but don't destroy argv[0]) 150*4bcd95a3SBarry Smith sys.argv = sys.argv[:1] + configure_options + sys.argv[1:] 151*4bcd95a3SBarry Smith framework = config.framework.Framework(['--configModules='+package+'.Configure', '--optionsModule='+package+'.compilerOptions']+sys.argv[1:], loadArgDB = 0) 152*4bcd95a3SBarry Smith framework.setup() 153*4bcd95a3SBarry Smith framework.configure(out = sys.stdout) 154*4bcd95a3SBarry Smith framework.storeSubstitutions(framework.argDB) 155*4bcd95a3SBarry Smith framework.printSummary() 156*4bcd95a3SBarry Smith framework.argDB.save(force = True) 157*4bcd95a3SBarry Smith framework.logClear() 158*4bcd95a3SBarry Smith framework.closeLog() 159*4bcd95a3SBarry Smith 160*4bcd95a3SBarry Smithif __name__ == '__main__': 161*4bcd95a3SBarry Smith configure([]) 162*4bcd95a3SBarry Smith``` 163*4bcd95a3SBarry Smith 164*4bcd95a3SBarry SmithThe PETSc `configure.py` is quite a bit longer than this, as it 165*4bcd95a3SBarry Smithperforms specialized command line processing, error handling, and 166*4bcd95a3SBarry Smithintegrating logging with the rest of PETSc. 167*4bcd95a3SBarry Smith 168*4bcd95a3SBarry SmithThe `config/package/Configure.py` module determines how the tree of 169*4bcd95a3SBarry Smith`Configure` objects is built and how the configure information is output. 170*4bcd95a3SBarry SmithThe `configure()` method of the module will be run by the `Framework` 171*4bcd95a3SBarry Smithobject created at the top level. A minimal `configure()` method would look 172*4bcd95a3SBarry Smithlike 173*4bcd95a3SBarry Smith 174*4bcd95a3SBarry Smith```python 175*4bcd95a3SBarry Smithdef configure(self): 176*4bcd95a3SBarry Smith self.framework.header = self.arch.arch+'/include/'+self.project+'conf.h' 177*4bcd95a3SBarry Smith self.framework.makeMacroHeader = self.arch.arch+'/conf/'+self.project+'variables' 178*4bcd95a3SBarry Smith self.framework.makeRuleHeader = self.arch.arch+'/conf/'+self.project+'rules' 179*4bcd95a3SBarry Smith 180*4bcd95a3SBarry Smith self.Dump() 181*4bcd95a3SBarry Smith self.logClear() 182*4bcd95a3SBarry Smith return 183*4bcd95a3SBarry Smith``` 184*4bcd95a3SBarry Smith 185*4bcd95a3SBarry SmithThe `Dump` method runs over the tree of configure modules, and outputs 186*4bcd95a3SBarry Smiththe data necessary for building, usually employing the 187*4bcd95a3SBarry Smith`addMakeMacro()`, `addMakeRule()` and `addDefine()` methods. These 188*4bcd95a3SBarry Smithmethods funnel output to the include and make files defined by the 189*4bcd95a3SBarry Smithframework object, and set at the beginning of this `configure()` 190*4bcd95a3SBarry Smithmethod. There is also some simple information that is often used, which 191*4bcd95a3SBarry Smithwe define in the initializer, 192*4bcd95a3SBarry Smith 193*4bcd95a3SBarry Smith```python 194*4bcd95a3SBarry Smithdef __init__(self, framework): 195*4bcd95a3SBarry Smith config.base.Configure.__init__(self, framework) 196*4bcd95a3SBarry Smith self.Project = 'PETSc' 197*4bcd95a3SBarry Smith self.project = self.Project.lower() 198*4bcd95a3SBarry Smith self.PROJECT = self.Project.upper() 199*4bcd95a3SBarry Smith self.headerPrefix = self.PROJECT 200*4bcd95a3SBarry Smith self.substPrefix = self.PROJECT 201*4bcd95a3SBarry Smith self.framework.Project = self.Project 202*4bcd95a3SBarry Smith return 203*4bcd95a3SBarry Smith``` 204*4bcd95a3SBarry Smith 205*4bcd95a3SBarry SmithMore sophisticated configure assemblies, like PETSc, output some other 206*4bcd95a3SBarry Smithcustom information, such as information about the machine, configure 207*4bcd95a3SBarry Smithprocess, and a script to recreate the configure run. 208*4bcd95a3SBarry Smith 209*4bcd95a3SBarry SmithThe `Package` configure module has two other main functions. First, top 210*4bcd95a3SBarry Smithlevel options can be defined in the `setupHelp()` method, 211*4bcd95a3SBarry Smith 212*4bcd95a3SBarry Smith```python 213*4bcd95a3SBarry Smithdef setupHelp(self, help): 214*4bcd95a3SBarry Smith import nargs 215*4bcd95a3SBarry Smith help.addArgument(self.Project, '-prefix=<path>', nargs.Arg(None, '', 'Specify location to install '+self.Project+' (eg. /usr/local)')) 216*4bcd95a3SBarry Smith help.addArgument(self.Project, '-load-path=<path>', nargs.Arg(None, os.path.join(os.getcwd(), 'modules'), 'Specify location of auxiliary modules')) 217*4bcd95a3SBarry Smith help.addArgument(self.Project, '-with-shared-libraries', nargs.ArgBool(None, 0, 'Make libraries shared')) 218*4bcd95a3SBarry Smith help.addArgument(self.Project, '-with-dynamic-loading', nargs.ArgBool(None, 0, 'Make libraries dynamic')) 219*4bcd95a3SBarry Smith return 220*4bcd95a3SBarry Smith``` 221*4bcd95a3SBarry Smith 222*4bcd95a3SBarry SmithThis uses the `BuildSystem` help facility that is used to define options 223*4bcd95a3SBarry Smithfor all configure modules. The first argument groups these options into 224*4bcd95a3SBarry Smitha section named for the package. The second task is to build the tree of 225*4bcd95a3SBarry Smithmodules for the configure run, using the `setupDependencies()` method. 226*4bcd95a3SBarry SmithA simple way to do this is by explicitly declaring dependencies, 227*4bcd95a3SBarry Smith 228*4bcd95a3SBarry Smith```python 229*4bcd95a3SBarry Smithdef setupDependencies(self, framework): 230*4bcd95a3SBarry Smith config.base.Configure.setupDependencies(self, framework) 231*4bcd95a3SBarry Smith self.setCompilers = framework.require('config.setCompilers', self) 232*4bcd95a3SBarry Smith self.arch = framework.require(self.Project+'.utilities.arch', self.setCompilers) 233*4bcd95a3SBarry Smith self.projectdir = framework.require(self.Project+'.utilities.projectdir', self.arch) 234*4bcd95a3SBarry Smith self.compilers = framework.require('config.compilers', self) 235*4bcd95a3SBarry Smith self.types = framework.require('config.types', self) 236*4bcd95a3SBarry Smith self.headers = framework.require('config.headers', self) 237*4bcd95a3SBarry Smith self.functions = framework.require('config.functions', self) 238*4bcd95a3SBarry Smith self.libraries = framework.require('config.libraries', self) 239*4bcd95a3SBarry Smith 240*4bcd95a3SBarry Smith self.compilers.headerPrefix = self.headerPrefix 241*4bcd95a3SBarry Smith self.types.headerPrefix = self.headerPrefix 242*4bcd95a3SBarry Smith self.headers.headerPrefix = self.headerPrefix 243*4bcd95a3SBarry Smith self.functions.headerPrefix = self.headerPrefix 244*4bcd95a3SBarry Smith self.libraries.headerPrefix = self.headerPrefix 245*4bcd95a3SBarry Smith``` 246*4bcd95a3SBarry Smith 247*4bcd95a3SBarry SmithThe `projectdir` and `arch` modules define the project root 248*4bcd95a3SBarry Smithdirectory and a build name so that multiple independent builds can be 249*4bcd95a3SBarry Smithmanaged. The `Framework.require()` method creates an edge in the 250*4bcd95a3SBarry Smithdependency graph for configure modules, and returns the module object so 251*4bcd95a3SBarry Smiththat it can be queried after the configure information is determined. 252*4bcd95a3SBarry SmithSetting the header prefix routes all the defines made inside those 253*4bcd95a3SBarry Smithmodules to our package configure header. We can also automatically 254*4bcd95a3SBarry Smithcreate configure modules based upon what we see on the filesystem, 255*4bcd95a3SBarry Smith 256*4bcd95a3SBarry Smith```python 257*4bcd95a3SBarry Smithfor utility in os.listdir(os.path.join('config', self.Project, 'utilities')): 258*4bcd95a3SBarry Smith (utilityName, ext) = os.path.splitext(utility) 259*4bcd95a3SBarry Smith if not utilityName.startswith('.') and not utilityName.startswith('#') and ext == '.py' and not utilityName == '__init__': 260*4bcd95a3SBarry Smith utilityObj = self.framework.require(self.Project+'.utilities.'+utilityName, self) 261*4bcd95a3SBarry Smith utilityObj.headerPrefix = self.headerPrefix 262*4bcd95a3SBarry Smith utilityObj.archProvider = self.arch 263*4bcd95a3SBarry Smith utilityObj.languageProvider = self.languages 264*4bcd95a3SBarry Smith utilityObj.precisionProvider = self.scalartypes 265*4bcd95a3SBarry Smith utilityObj.installDirProvider = self.installdir 266*4bcd95a3SBarry Smith utilityObj.externalPackagesDirProvider = self.externalpackagesdir 267*4bcd95a3SBarry Smith setattr(self, utilityName.lower(), utilityObj) 268*4bcd95a3SBarry Smith``` 269*4bcd95a3SBarry Smith 270*4bcd95a3SBarry SmithThe provider modules customize the information given to the module based 271*4bcd95a3SBarry Smithupon settings for our package. For example, PETSc can be compiled with a 272*4bcd95a3SBarry Smithscalar type that is single, double, or quad precision, and thus has a 273*4bcd95a3SBarry Smith`precisionProvider`. If a package does not have this capability, the 274*4bcd95a3SBarry Smithprovider setting can be omitted. 275*4bcd95a3SBarry Smith 276*4bcd95a3SBarry Smith## Main objects 277*4bcd95a3SBarry Smith 278*4bcd95a3SBarry Smith### Framework 279*4bcd95a3SBarry Smith 280*4bcd95a3SBarry SmithThe `config.framework.Framework` object serves as the central control 281*4bcd95a3SBarry Smithfor a configure run. It maintains a graph of all the configure modules 282*4bcd95a3SBarry Smithinvolved, which is also used to track dependencies between them. It 283*4bcd95a3SBarry Smithinitiates the run, compiles the results, and handles the final output. 284*4bcd95a3SBarry SmithIt maintains the help list for all options available in the run. The 285*4bcd95a3SBarry Smith`setup()` method performs generic `Script` setup and then is called 286*4bcd95a3SBarry Smithrecursively on all the child modules. The `cleanup()` method performs 287*4bcd95a3SBarry Smiththe final output and logging actions, 288*4bcd95a3SBarry Smith 289*4bcd95a3SBarry Smith- Substitute files 290*4bcd95a3SBarry Smith- Output configure header 291*4bcd95a3SBarry Smith- Log filesystem actions 292*4bcd95a3SBarry Smith 293*4bcd95a3SBarry SmithChildren may be added to the Framework using `addChild()` or 294*4bcd95a3SBarry Smith`getChild()`, but the far more frequent method is to use 295*4bcd95a3SBarry Smith`require()`. Here a module is requested, as in `getChild()`, but it 296*4bcd95a3SBarry Smithis also required to run before another module, usually the one executing 297*4bcd95a3SBarry Smiththe `require()`. This provides a simple local interface to establish 298*4bcd95a3SBarry Smithdependencies between the child modules, and provides a partial order on 299*4bcd95a3SBarry Smiththe children to the Framework. 300*4bcd95a3SBarry Smith 301*4bcd95a3SBarry SmithA backwards compatibility mode is provided for which the user specifies 302*4bcd95a3SBarry Smitha configure header and set of files to experience substitution, 303*4bcd95a3SBarry Smithmirroring the common usage of Autoconf. Slight improvements have been 304*4bcd95a3SBarry Smithmade in that all defines are now guarded, various prefixes are allowed 305*4bcd95a3SBarry Smithfor defines and substitutions, and C specific constructs such as 306*4bcd95a3SBarry Smithfunction prototypes and typedefs are removed to a separate header. 307*4bcd95a3SBarry SmithHowever, this is not the intended future usage. The use of configure 308*4bcd95a3SBarry Smithmodules by other modules in the same run provides a model for the 309*4bcd95a3SBarry Smithsuggested interaction of a new build system with the Framework. If a 310*4bcd95a3SBarry Smithmodule requires another, it merely executes a `require()`. For 311*4bcd95a3SBarry Smithinstance, the PETSc configure module for hypre requires information 312*4bcd95a3SBarry Smithabout MPI, and thus contains 313*4bcd95a3SBarry Smith 314*4bcd95a3SBarry Smith```python 315*4bcd95a3SBarry Smithself.mpi = self.framework.require("config.packages.MPI", self) 316*4bcd95a3SBarry Smith``` 317*4bcd95a3SBarry Smith 318*4bcd95a3SBarry SmithNotice that passing self for the last arguments means that the MPI 319*4bcd95a3SBarry Smithmodule will run before the hypre module. Furthermore, we save the 320*4bcd95a3SBarry Smithresulting object as `self.mpi` so that we may interrogate it later. 321*4bcd95a3SBarry Smithhypre can initially test whether MPI was indeed found using 322*4bcd95a3SBarry Smith`self.mpi.found`. When hypre requires the list of MPI libraries in 323*4bcd95a3SBarry Smithorder to link a test object, the module can use `self.mpi.lib`. 324*4bcd95a3SBarry Smith 325*4bcd95a3SBarry Smith### Base 326*4bcd95a3SBarry Smith 327*4bcd95a3SBarry SmithThe `config.base.Configure` is the base class for all configure 328*4bcd95a3SBarry Smithobjects. It handles several types of interaction. First, it has hooks 329*4bcd95a3SBarry Smiththat allow the Framework to initialize it correctly. The Framework will 330*4bcd95a3SBarry Smithfirst instantiate the object and call `setupDependencies()`. All 331*4bcd95a3SBarry Smith`require()` calls should be made in that method. The Framework will 332*4bcd95a3SBarry Smiththen call `configure()`. If it succeeds, the object will be marked as 333*4bcd95a3SBarry Smithconfigured. Second, all configure tests should be run using 334*4bcd95a3SBarry Smith`executeTest()` which formats the output and adds metadata for the 335*4bcd95a3SBarry Smithlog. 336*4bcd95a3SBarry Smith 337*4bcd95a3SBarry SmithThird, all tests that involve preprocessing, compiling, linking, and 338*4bcd95a3SBarry Smithrunning operator through `base`. Two forms of this check are provided 339*4bcd95a3SBarry Smithfor each operation. The first is an "output" form which is intended to 340*4bcd95a3SBarry Smithprovide the status and complete output of the command. The second, or 341*4bcd95a3SBarry Smith"check" form will return a success or failure indication based upon the 342*4bcd95a3SBarry Smithstatus and output. The routines are 343*4bcd95a3SBarry Smith 344*4bcd95a3SBarry Smith```python 345*4bcd95a3SBarry SmithoutputPreprocess(), checkPreprocess(), preprocess() 346*4bcd95a3SBarry SmithoutputCompile(), checkCompile() 347*4bcd95a3SBarry SmithoutputLink(), checkLink() 348*4bcd95a3SBarry SmithoutputRun(), checkRun() 349*4bcd95a3SBarry Smith``` 350*4bcd95a3SBarry Smith 351*4bcd95a3SBarry SmithThe language used for these operation is managed with a stack, similar 352*4bcd95a3SBarry Smithto Autoconf, using `pushLanguage()` and `popLanguage()`. We also 353*4bcd95a3SBarry Smithprovide special forms used to check for valid compiler and linker flags, 354*4bcd95a3SBarry Smithoptionally adding them to the defaults. 355*4bcd95a3SBarry Smith 356*4bcd95a3SBarry Smith```python 357*4bcd95a3SBarry SmithcheckCompilerFlag(), addCompilerFlag() 358*4bcd95a3SBarry SmithcheckLinkerFlag(), addLinkerFlag() 359*4bcd95a3SBarry Smith``` 360*4bcd95a3SBarry Smith 361*4bcd95a3SBarry SmithYou can also use `getExecutable()` to search for executables. 362*4bcd95a3SBarry Smith 363*4bcd95a3SBarry SmithAfter configure tests have been run, various kinds of output can be 364*4bcd95a3SBarry Smithgenerated.A #define statement can be added to the configure header using 365*4bcd95a3SBarry Smith`addDefine()`, and `addTypedef()` and `addPrototype()` also put 366*4bcd95a3SBarry Smithinformation in this header file. Using `addMakeMacro()` and 367*4bcd95a3SBarry Smith`addMakeRule()` will add make macros and rules to the output makefiles 368*4bcd95a3SBarry Smithspecified in the framework. In addition we provide `addSubstitution()` 369*4bcd95a3SBarry Smithand `addArgumentSubstitution()` to mimic the behavior of Autoconf if 370*4bcd95a3SBarry Smithnecessary. The object may define a `headerPrefix` member, which will 371*4bcd95a3SBarry Smithbe appended, followed by an underscore, to every define which is output 372*4bcd95a3SBarry Smithfrom it. Similarly, a `substPrefix` can be defined which applies to 373*4bcd95a3SBarry Smithevery substitution from the object. Typedefs and function prototypes are 374*4bcd95a3SBarry Smithplaced in a separate header in order to accommodate languages such as 375*4bcd95a3SBarry SmithFortran whose preprocessor can sometimes fail at these statements. 376