1525d6f2eSBarry Smith#!/usr/bin/env python 2525d6f2eSBarry Smith# 3*a95d84e0SBarry Smith# Builds a iOS static library of PETSc 4525d6f2eSBarry Smith# 5*a95d84e0SBarry Smith# Before using remove /usr/include/mpi.h and /Developer/SDKs/MacOSX10.5.sdk/usr/include/mpi.h or 6525d6f2eSBarry Smith# Xcode will use those instead of the MPIuni one we point to 7525d6f2eSBarry Smith# 8525d6f2eSBarry Smith# export PETSC_ARCH=arch-ios 9*a95d84e0SBarry Smith# 10525d6f2eSBarry Smith# ./systems/Apple/iOS/bin/arch-ios.py [use --with-debugging=0 to get iPhone/iPad version, otherwise creates simulator version] 11525d6f2eSBarry Smith# this sets up the appropriate configuration file 12525d6f2eSBarry Smith# 13525d6f2eSBarry Smith# ./systems/Apple/iOS/bin/iosbuilder.py 14525d6f2eSBarry Smith# this creates the PETSc iPhone/iPad library 15525d6f2eSBarry Smith# this will open Xcode and give you directions to follow 16525d6f2eSBarry Smith# 17*a95d84e0SBarry Smith# open systems/Apple/iOS/examples/examples.xcodeproj 18525d6f2eSBarry Smith# Project -> Edit Project Setting -> Configuration (make sure it is Release or Debug depending on if you used --with-debugging=0) 19525d6f2eSBarry Smith# Build -> Build and Debug 20525d6f2eSBarry Smith# 21525d6f2eSBarry Smithimport os, sys 22525d6f2eSBarry Smith 23525d6f2eSBarry Smithsys.path.insert(0, os.path.join(os.environ['PETSC_DIR'], 'config')) 24525d6f2eSBarry Smithsys.path.insert(0, os.path.join(os.environ['PETSC_DIR'], 'config', 'BuildSystem')) 25525d6f2eSBarry Smith 26525d6f2eSBarry Smithimport script 27525d6f2eSBarry Smith 28525d6f2eSBarry Smithclass PETScMaker(script.Script): 29525d6f2eSBarry Smith def __init__(self): 30525d6f2eSBarry Smith import RDict 31525d6f2eSBarry Smith import os 32525d6f2eSBarry Smith 33525d6f2eSBarry Smith argDB = RDict.RDict(None, None, 0, 0, readonly = True) 34525d6f2eSBarry Smith argDB.saveFilename = os.path.join(os.environ['PETSC_DIR'], os.environ['PETSC_ARCH'], 'conf', 'RDict.db') 35525d6f2eSBarry Smith argDB.load() 36525d6f2eSBarry Smith script.Script.__init__(self, argDB = argDB) 37525d6f2eSBarry Smith self.log = sys.stdout 38525d6f2eSBarry Smith return 39525d6f2eSBarry Smith 40525d6f2eSBarry Smith def setupModules(self): 41525d6f2eSBarry Smith self.mpi = self.framework.require('config.packages.MPI', None) 42525d6f2eSBarry Smith self.base = self.framework.require('config.base', None) 43525d6f2eSBarry Smith self.setCompilers = self.framework.require('config.setCompilers', None) 44525d6f2eSBarry Smith self.arch = self.framework.require('PETSc.utilities.arch', None) 45525d6f2eSBarry Smith self.petscdir = self.framework.require('PETSc.utilities.petscdir', None) 46525d6f2eSBarry Smith self.languages = self.framework.require('PETSc.utilities.languages', None) 47525d6f2eSBarry Smith self.debugging = self.framework.require('PETSc.utilities.debugging', None) 48525d6f2eSBarry Smith self.make = self.framework.require('config.programs', None) 49525d6f2eSBarry Smith self.compilers = self.framework.require('config.compilers', None) 50525d6f2eSBarry Smith self.types = self.framework.require('config.types', None) 51525d6f2eSBarry Smith self.headers = self.framework.require('config.headers', None) 52525d6f2eSBarry Smith self.functions = self.framework.require('config.functions', None) 53525d6f2eSBarry Smith self.libraries = self.framework.require('config.libraries', None) 54525d6f2eSBarry Smith self.scalarType = self.framework.require('PETSc.utilities.scalarTypes', None) 55525d6f2eSBarry Smith self.memAlign = self.framework.require('PETSc.utilities.memAlign', None) 56525d6f2eSBarry Smith self.libraryOptions= self.framework.require('PETSc.utilities.libraryOptions', None) 57525d6f2eSBarry Smith self.compilerFlags = self.framework.require('config.compilerFlags', self) 58525d6f2eSBarry Smith return 59525d6f2eSBarry Smith 60525d6f2eSBarry Smith def setupHelp(self, help): 61525d6f2eSBarry Smith import nargs 62525d6f2eSBarry Smith 63525d6f2eSBarry Smith help = script.Script.setupHelp(self, help) 64525d6f2eSBarry Smith help.addArgument('RepManager', '-rootDir', nargs.ArgDir(None, os.environ['PETSC_DIR'], 'The root directory for this build', isTemporary = 1)) 65525d6f2eSBarry Smith help.addArgument('RepManager', '-dryRun', nargs.ArgBool(None, False, 'Only output what would be run', isTemporary = 1)) 6633be3048SBarry Smith help.addArgument('RepManager', '-skipXCode', nargs.ArgBool(None, False, 'Do not run XCode application/files have not been added/removed', isTemporary = 1)) 67525d6f2eSBarry Smith help.addArgument('RepManager', '-verbose', nargs.ArgInt(None, 0, 'The verbosity level', min = 0, isTemporary = 1)) 68525d6f2eSBarry Smith return help 69525d6f2eSBarry Smith 70525d6f2eSBarry Smith def setup(self): 71525d6f2eSBarry Smith script.Script.setup(self) 72525d6f2eSBarry Smith self.framework = self.loadConfigure() 73525d6f2eSBarry Smith self.setupModules() 74525d6f2eSBarry Smith return 75525d6f2eSBarry Smith 76525d6f2eSBarry Smith @property 77525d6f2eSBarry Smith def verbose(self): 78525d6f2eSBarry Smith '''The verbosity level''' 79525d6f2eSBarry Smith return self.argDB['verbose'] 80525d6f2eSBarry Smith 81525d6f2eSBarry Smith @property 8233be3048SBarry Smith def skipXCode(self): 8333be3048SBarry Smith '''Skip XCode application''' 8433be3048SBarry Smith return self.argDB['skipXCode'] 8533be3048SBarry Smith 8633be3048SBarry Smith @property 87525d6f2eSBarry Smith def dryRun(self): 88525d6f2eSBarry Smith '''Flag for only output of what would be run''' 89525d6f2eSBarry Smith return self.argDB['dryRun'] 90525d6f2eSBarry Smith 91525d6f2eSBarry Smith def getPackageInfo(self): 92525d6f2eSBarry Smith packageIncludes = [] 93525d6f2eSBarry Smith packageLibs = [] 94525d6f2eSBarry Smith for p in self.framework.packages: 95525d6f2eSBarry Smith # Could put on compile line, self.addDefine('HAVE_'+i.PACKAGE, 1) 96525d6f2eSBarry Smith if hasattr(p, 'lib'): 97525d6f2eSBarry Smith if not isinstance(p.lib, list): 98525d6f2eSBarry Smith packageLibs.append(p.lib) 99525d6f2eSBarry Smith else: 100525d6f2eSBarry Smith packageLibs.extend(p.lib) 101525d6f2eSBarry Smith if hasattr(p, 'include'): 102525d6f2eSBarry Smith if not isinstance(p.include, list): 103525d6f2eSBarry Smith packageIncludes.append(p.include) 104525d6f2eSBarry Smith else: 105525d6f2eSBarry Smith packageIncludes.extend(p.include) 106525d6f2eSBarry Smith packageLibs = self.libraries.toStringNoDupes(packageLibs+self.libraries.math) 107525d6f2eSBarry Smith packageIncludes = self.headers.toStringNoDupes(packageIncludes) 108525d6f2eSBarry Smith return packageIncludes, packageLibs 109525d6f2eSBarry Smith 110525d6f2eSBarry Smith def buildDir(self, dirname): 111525d6f2eSBarry Smith ''' This is run in a PETSc source directory''' 112525d6f2eSBarry Smith if self.verbose: print 'Entering '+dirname 113525d6f2eSBarry Smith os.chdir(dirname) 114525d6f2eSBarry Smith l = len(os.environ['PETSC_DIR']) 115525d6f2eSBarry Smith basedir = os.path.join(os.environ['PETSC_DIR'],os.environ['PETSC_ARCH'],'xcode-links') 116525d6f2eSBarry Smith #newdirname = os.path.join(basedir,dirname[l+1:]) 117525d6f2eSBarry Smith #os.mkdir(newdirname) 118525d6f2eSBarry Smith 119525d6f2eSBarry Smith 120525d6f2eSBarry Smith # Get list of source files in the directory 121525d6f2eSBarry Smith cnames = [] 122525d6f2eSBarry Smith onames = [] 123525d6f2eSBarry Smith fnames = [] 124525d6f2eSBarry Smith hnames = [] 125525d6f2eSBarry Smith for f in os.listdir(dirname): 126525d6f2eSBarry Smith ext = os.path.splitext(f)[1] 127525d6f2eSBarry Smith if ext == '.c': 128525d6f2eSBarry Smith cnames.append(f) 129525d6f2eSBarry Smith onames.append(f.replace('.c', '.o')) 130525d6f2eSBarry Smith if ext == '.h': 131525d6f2eSBarry Smith hnames.append(f) 132525d6f2eSBarry Smith if cnames: 133525d6f2eSBarry Smith if self.verbose: print 'Linking C files',cnames 134525d6f2eSBarry Smith for i in cnames: 135525d6f2eSBarry Smith j = i[l+1:] 136*a95d84e0SBarry Smith if not os.path.islink(os.path.join(basedir,i)) and not i.startswith('.') and i.find(".BACKUP") == -1 and i.find(".LOCAL") == -1 and i.find(".BASE") == -1: 13733be3048SBarry Smith if i.endswith('openglops.c') and not os.path.islink(os.path.join(basedir,'openglops.m')): 138f72c6c23SBarry Smith os.symlink(os.path.join(dirname,i),os.path.join(basedir,'openglops.m')) 139f72c6c23SBarry Smith else: 140525d6f2eSBarry Smith os.symlink(os.path.join(dirname,i),os.path.join(basedir,i)) 141525d6f2eSBarry Smith # do not need to link these because xcode project points to original source code directory 142525d6f2eSBarry Smith #if hnames: 143525d6f2eSBarry Smith # if self.verbose: print 'Linking h files',hnames 144525d6f2eSBarry Smith # for i in hnames: 145525d6f2eSBarry Smith # if not os.path.islink(os.path.join(basedir,i)): 146525d6f2eSBarry Smith # os.symlink(os.path.join(dirname,i),os.path.join(basedir,i)) 147525d6f2eSBarry Smith return 148525d6f2eSBarry Smith 149525d6f2eSBarry Smith def checkDir(self, dirname): 150525d6f2eSBarry Smith '''Checks whether we should recurse into this directory 151525d6f2eSBarry Smith - Excludes projects directory 152525d6f2eSBarry Smith - Excludes examples directory 153525d6f2eSBarry Smith - Excludes contrib directory 154525d6f2eSBarry Smith - Excludes tutorials directory 155525d6f2eSBarry Smith - Excludes benchmarks directory 156525d6f2eSBarry Smith - Checks makefile to see if compiler is allowed to visit this directory for this configuration''' 157525d6f2eSBarry Smith# print self.functions.functions 158525d6f2eSBarry Smith# print self.base.defines 159525d6f2eSBarry Smith base = os.path.basename(dirname) 160525d6f2eSBarry Smith 161525d6f2eSBarry Smith if base == 'examples': return False 162525d6f2eSBarry Smith if base == 'projects': return False 163525d6f2eSBarry Smith if base.startswith('ftn-') or base.startswith('f90-'): return False 164525d6f2eSBarry Smith if base == 'contrib': return False 165525d6f2eSBarry Smith if base == 'tutorials': return False 166525d6f2eSBarry Smith if base == 'benchmarks': return False 167f72c6c23SBarry Smith if base == 'systems': return False 168*a95d84e0SBarry Smith# for some reason agrmes is in the repository but not used! 169*a95d84e0SBarry Smith if base == 'agmres': return False 170*a95d84e0SBarry Smith if base == 'test-dir': return False 171525d6f2eSBarry Smith if base.startswith('arch-'): return False 172525d6f2eSBarry Smith 173525d6f2eSBarry Smith import re 174525d6f2eSBarry Smith reg = re.compile(' [ ]*') 175525d6f2eSBarry Smith fname = os.path.join(dirname, 'makefile') 176525d6f2eSBarry Smith if not os.path.isfile(fname): 177525d6f2eSBarry Smith if os.path.isfile(os.path.join(dirname, 'Makefile')): print 'ERROR: Change Makefile to makefile in',dirname 178525d6f2eSBarry Smith return False 179525d6f2eSBarry Smith fd = open(fname) 180525d6f2eSBarry Smith text = fd.readline() 181525d6f2eSBarry Smith while text: 182525d6f2eSBarry Smith if text.startswith('#requires'): 183525d6f2eSBarry Smith text = text[9:-1].strip() 184525d6f2eSBarry Smith text = reg.sub(' ',text) 185525d6f2eSBarry Smith rtype = text.split(' ')[0] 186525d6f2eSBarry Smith rvalue = text.split(' ')[1] 187525d6f2eSBarry Smith 188525d6f2eSBarry Smith if rvalue == "'"+'PETSC_HAVE_FORTRAN'+"'" or rvalue == "'"+'PETSC_USING_F90'+"'" or rvalue == "'"+'PETSC_USING_F2003'+"'": 189525d6f2eSBarry Smith if not hasattr(self.compilers, 'FC'): 190525d6f2eSBarry Smith if self.verbose: print 'Rejecting',dirname,'because fortran is not being used' 191525d6f2eSBarry Smith return 0 192525d6f2eSBarry Smith elif rvalue == "'"+'PETSC_USE_LOG'+"'": 193525d6f2eSBarry Smith if not self.libraryOptions.useLog: 194525d6f2eSBarry Smith if self.verbose: print 'Rejecting',dirname,'because logging is turned off' 195525d6f2eSBarry Smith return 0 196525d6f2eSBarry Smith elif rvalue == "'"+'PETSC_USE_FORTRAN_KERNELS'+"'": 197525d6f2eSBarry Smith if not self.libraryOptions.useFortranKernels: 198525d6f2eSBarry Smith if self.verbose: print 'Rejecting',dirname,'because fortran kernels are turned off' 199525d6f2eSBarry Smith return 0 200525d6f2eSBarry Smith elif rtype == 'scalar' and not self.scalarType.scalartype == rvalue: 201525d6f2eSBarry Smith if self.verbose: print 'Rejecting',dirname,'because scalar type '+self.scalarType.scalartype+' is not '+rvalue 202525d6f2eSBarry Smith return 0 203525d6f2eSBarry Smith elif rtype == 'language': 204525d6f2eSBarry Smith if rvalue == 'CXXONLY' and self.languages.clanguage == 'C': 205525d6f2eSBarry Smith if self.verbose: print 'Rejecting',dirname,'because language is '+self.languages.clanguage+' is not C++' 206525d6f2eSBarry Smith return 0 207525d6f2eSBarry Smith elif rtype == 'precision' and not rvalue == self.scalarType.precision: 208525d6f2eSBarry Smith if self.verbose: print 'Rejecting',dirname,'because precision '+self.scalarType.precision+' is not '+rvalue 209525d6f2eSBarry Smith return 0 210525d6f2eSBarry Smith elif rtype == 'package': 211525d6f2eSBarry Smith found = 0 212525d6f2eSBarry Smith if self.mpi.usingMPIUni: 213525d6f2eSBarry Smith pname = 'PETSC_HAVE_MPIUNI' 214525d6f2eSBarry Smith pname = "'"+pname+"'" 215525d6f2eSBarry Smith if pname == rvalue: found = 1 216525d6f2eSBarry Smith for i in self.framework.packages: 217525d6f2eSBarry Smith pname = 'PETSC_HAVE_'+i.PACKAGE 218525d6f2eSBarry Smith pname = "'"+pname+"'" 219525d6f2eSBarry Smith if pname == rvalue: found = 1 220525d6f2eSBarry Smith if not found: 221*a95d84e0SBarry Smith for i in self.base.defines: 222*a95d84e0SBarry Smith pname = 'PETSC_'+i.upper() 223*a95d84e0SBarry Smith pname = "'"+pname+"'" 224*a95d84e0SBarry Smith if pname == rvalue: found = 1 225*a95d84e0SBarry Smith if not found: 226525d6f2eSBarry Smith if self.verbose: print 'Rejecting',dirname,'because package '+rvalue+' does not exist' 227525d6f2eSBarry Smith return 0 228525d6f2eSBarry Smith elif rtype == 'define': 229525d6f2eSBarry Smith found = 0 230525d6f2eSBarry Smith for i in self.base.defines: 231525d6f2eSBarry Smith pname = 'PETSC_'+i.upper() 232525d6f2eSBarry Smith pname = "'"+pname+"'" 233525d6f2eSBarry Smith if pname == rvalue: found = 1 234525d6f2eSBarry Smith if not found: 235525d6f2eSBarry Smith if self.verbose: print 'Rejecting',dirname,'because define '+rvalue+' does not exist' 236525d6f2eSBarry Smith return 0 237525d6f2eSBarry Smith elif rtype == 'function': 238525d6f2eSBarry Smith found = 0 239525d6f2eSBarry Smith for i in self.functions.functions: 240525d6f2eSBarry Smith pname = 'PETSC_HAVE_'+i.upper() 241525d6f2eSBarry Smith pname = "'"+pname+"'" 242525d6f2eSBarry Smith# print pname 243525d6f2eSBarry Smith# print rvalue 244525d6f2eSBarry Smith if pname == rvalue: found = 1 245525d6f2eSBarry Smith if not found: 246525d6f2eSBarry Smith if self.verbose: print 'Rejecting',dirname,'because function '+rvalue+' does not exist' 247525d6f2eSBarry Smith return 0 248525d6f2eSBarry Smith 249525d6f2eSBarry Smith text = fd.readline() 250525d6f2eSBarry Smith fd.close() 251525d6f2eSBarry Smith return True 252525d6f2eSBarry Smith 253525d6f2eSBarry Smith def buildAll(self, rootDir = None): 254525d6f2eSBarry Smith import shutil 255525d6f2eSBarry Smith self.setup() 256525d6f2eSBarry Smith if rootDir is None: 257525d6f2eSBarry Smith rootDir = self.argDB['rootDir'] 258525d6f2eSBarry Smith if not self.checkDir(rootDir): 259525d6f2eSBarry Smith print 'Nothing to be done' 260525d6f2eSBarry Smith if rootDir == os.environ['PETSC_DIR']: 261525d6f2eSBarry Smith basedir = os.path.join(self.petscdir.dir, self.arch.arch, 'xcode-links') 262525d6f2eSBarry Smith if os.path.isdir(basedir): 263525d6f2eSBarry Smith if self.verbose: print 'Removing '+basedir 264525d6f2eSBarry Smith shutil.rmtree(basedir) 265525d6f2eSBarry Smith os.mkdir(basedir) 266525d6f2eSBarry Smith for root, dirs, files in os.walk(rootDir): 267525d6f2eSBarry Smith self.buildDir(root) 268525d6f2eSBarry Smith for badDir in [d for d in dirs if not self.checkDir(os.path.join(root, d))]: 269525d6f2eSBarry Smith dirs.remove(badDir) 270525d6f2eSBarry Smith 27133be3048SBarry Smith if not self.skipXCode: 27233be3048SBarry Smith 273*a95d84e0SBarry Smith print 'In Xcode mouse click on Other Sources then xcode-links and the delete key, then' 274525d6f2eSBarry Smith print 'control mouse click on "Other Sources" and select "Add files to PETSc ...", then' 275525d6f2eSBarry Smith print 'in the finder window locate ${PETSC_DIR}/arch-ios/xcode-links and select it. Now' 276525d6f2eSBarry Smith print 'exit Xcode' 277525d6f2eSBarry Smith 278525d6f2eSBarry Smith try: 279525d6f2eSBarry Smith import subprocess 280525d6f2eSBarry Smith subprocess.call('cd '+os.path.join(os.environ['PETSC_DIR'],'systems','Apple','iOS','PETSc')+';open -W PETSc.xcodeproj', shell=True) 281525d6f2eSBarry Smith except RuntimeError, e: 282525d6f2eSBarry Smith raise RuntimeError('Error opening xcode project '+str(e)) 283525d6f2eSBarry Smith 284525d6f2eSBarry Smith 285*a95d84e0SBarry Smith sdk = ' -sdk iphonesimulator7.1 ' 286525d6f2eSBarry Smith destination = 'iphonesimulator' 287525d6f2eSBarry Smith debug = 'Debug' 288525d6f2eSBarry Smith debugdir = 'Debug-'+destination 289525d6f2eSBarry Smith if not self.compilerFlags.debugging: 290525d6f2eSBarry Smith debug = 'Release' 291525d6f2eSBarry Smith debugdir = 'Release-'+destination 292525d6f2eSBarry Smith try: 293525d6f2eSBarry Smith output,err,ret = self.executeShellCommand('cd '+os.path.join(os.environ['PETSC_DIR'],'systems','Apple','iOS','PETSc')+';xcodebuild -configuration '+debug+sdk, timeout=3000, log = self.log) 294525d6f2eSBarry Smith except RuntimeError, e: 295525d6f2eSBarry Smith raise RuntimeError('Error making iPhone/iPad version of PETSc libraries: '+str(e)) 296525d6f2eSBarry Smith 297525d6f2eSBarry Smith liblocation = os.path.join(os.environ['PETSC_DIR'],'systems','Apple','iOS','PETSc','build',debugdir,'libPETSc.a') 298525d6f2eSBarry Smith if not os.path.exists(liblocation): 299525d6f2eSBarry Smith raise RuntimeError('Error library '+liblocation+' not created') 300525d6f2eSBarry Smith try: 301525d6f2eSBarry Smith output,err,ret = self.executeShellCommand('mv -f '+liblocation+' '+os.path.join(os.environ['PETSC_DIR'],os.environ['PETSC_ARCH'],'lib'), timeout=30, log = self.log) 302525d6f2eSBarry Smith except RuntimeError, e: 303525d6f2eSBarry Smith raise RuntimeError('Error copying iPhone/iPad version of PETSc libraries: '+str(e)) 304525d6f2eSBarry Smith 305525d6f2eSBarry Smith return 306525d6f2eSBarry Smith 307525d6f2eSBarry Smithdef noCheckCommand(command, status, output, error): 308525d6f2eSBarry Smith ''' Do no check result''' 309525d6f2eSBarry Smith return 310525d6f2eSBarry Smith noCheckCommand = staticmethod(noCheckCommand) 311525d6f2eSBarry Smith 312525d6f2eSBarry Smithif __name__ == '__main__': 313525d6f2eSBarry Smith PETScMaker().buildAll() 314