1*525d6f2eSBarry Smith#!/usr/bin/env python 2*525d6f2eSBarry Smith# 3*525d6f2eSBarry Smith# Builds a iPhone/iPad static library of PETSc 4*525d6f2eSBarry Smith# 5*525d6f2eSBarry Smith# Before using removed /usr/include/mpi.h and /Developer/SDKs/MacOSX10.5.sdk/usr/include/mpi.h or 6*525d6f2eSBarry Smith# Xcode will use those instead of the MPIuni one we point to 7*525d6f2eSBarry Smith# 8*525d6f2eSBarry Smith# export PETSC_ARCH=arch-ios 9*525d6f2eSBarry Smith 10*525d6f2eSBarry Smith# ./systems/Apple/iOS/bin/arch-ios.py [use --with-debugging=0 to get iPhone/iPad version, otherwise creates simulator version] 11*525d6f2eSBarry Smith# this sets up the appropriate configuration file 12*525d6f2eSBarry Smith# 13*525d6f2eSBarry Smith# ./systems/Apple/iOS/bin/iosbuilder.py 14*525d6f2eSBarry Smith# this creates the PETSc iPhone/iPad library 15*525d6f2eSBarry Smith# this will open Xcode and give you directions to follow 16*525d6f2eSBarry Smith# 17*525d6f2eSBarry Smith# open xcode/examples/examples.xcodeproj 18*525d6f2eSBarry Smith# Project -> Edit Project Setting -> Configuration (make sure it is Release or Debug depending on if you used --with-debugging=0) 19*525d6f2eSBarry Smith# Build -> Build and Debug 20*525d6f2eSBarry Smith# 21*525d6f2eSBarry Smithimport os, sys 22*525d6f2eSBarry Smith 23*525d6f2eSBarry Smithsys.path.insert(0, os.path.join(os.environ['PETSC_DIR'], 'config')) 24*525d6f2eSBarry Smithsys.path.insert(0, os.path.join(os.environ['PETSC_DIR'], 'config', 'BuildSystem')) 25*525d6f2eSBarry Smith 26*525d6f2eSBarry Smithimport script 27*525d6f2eSBarry Smith 28*525d6f2eSBarry Smithclass PETScMaker(script.Script): 29*525d6f2eSBarry Smith def __init__(self): 30*525d6f2eSBarry Smith import RDict 31*525d6f2eSBarry Smith import os 32*525d6f2eSBarry Smith 33*525d6f2eSBarry Smith argDB = RDict.RDict(None, None, 0, 0, readonly = True) 34*525d6f2eSBarry Smith argDB.saveFilename = os.path.join(os.environ['PETSC_DIR'], os.environ['PETSC_ARCH'], 'conf', 'RDict.db') 35*525d6f2eSBarry Smith argDB.load() 36*525d6f2eSBarry Smith script.Script.__init__(self, argDB = argDB) 37*525d6f2eSBarry Smith self.log = sys.stdout 38*525d6f2eSBarry Smith return 39*525d6f2eSBarry Smith 40*525d6f2eSBarry Smith def setupModules(self): 41*525d6f2eSBarry Smith self.mpi = self.framework.require('config.packages.MPI', None) 42*525d6f2eSBarry Smith self.base = self.framework.require('config.base', None) 43*525d6f2eSBarry Smith self.setCompilers = self.framework.require('config.setCompilers', None) 44*525d6f2eSBarry Smith self.arch = self.framework.require('PETSc.utilities.arch', None) 45*525d6f2eSBarry Smith self.petscdir = self.framework.require('PETSc.utilities.petscdir', None) 46*525d6f2eSBarry Smith self.languages = self.framework.require('PETSc.utilities.languages', None) 47*525d6f2eSBarry Smith self.debugging = self.framework.require('PETSc.utilities.debugging', None) 48*525d6f2eSBarry Smith self.make = self.framework.require('config.programs', None) 49*525d6f2eSBarry Smith self.compilers = self.framework.require('config.compilers', None) 50*525d6f2eSBarry Smith self.types = self.framework.require('config.types', None) 51*525d6f2eSBarry Smith self.headers = self.framework.require('config.headers', None) 52*525d6f2eSBarry Smith self.functions = self.framework.require('config.functions', None) 53*525d6f2eSBarry Smith self.libraries = self.framework.require('config.libraries', None) 54*525d6f2eSBarry Smith self.scalarType = self.framework.require('PETSc.utilities.scalarTypes', None) 55*525d6f2eSBarry Smith self.memAlign = self.framework.require('PETSc.utilities.memAlign', None) 56*525d6f2eSBarry Smith self.libraryOptions= self.framework.require('PETSc.utilities.libraryOptions', None) 57*525d6f2eSBarry Smith self.compilerFlags = self.framework.require('config.compilerFlags', self) 58*525d6f2eSBarry Smith return 59*525d6f2eSBarry Smith 60*525d6f2eSBarry Smith def setupHelp(self, help): 61*525d6f2eSBarry Smith import nargs 62*525d6f2eSBarry Smith 63*525d6f2eSBarry Smith help = script.Script.setupHelp(self, help) 64*525d6f2eSBarry Smith help.addArgument('RepManager', '-rootDir', nargs.ArgDir(None, os.environ['PETSC_DIR'], 'The root directory for this build', isTemporary = 1)) 65*525d6f2eSBarry Smith help.addArgument('RepManager', '-dryRun', nargs.ArgBool(None, False, 'Only output what would be run', isTemporary = 1)) 66*525d6f2eSBarry Smith help.addArgument('RepManager', '-verbose', nargs.ArgInt(None, 0, 'The verbosity level', min = 0, isTemporary = 1)) 67*525d6f2eSBarry Smith return help 68*525d6f2eSBarry Smith 69*525d6f2eSBarry Smith def setup(self): 70*525d6f2eSBarry Smith script.Script.setup(self) 71*525d6f2eSBarry Smith self.framework = self.loadConfigure() 72*525d6f2eSBarry Smith self.setupModules() 73*525d6f2eSBarry Smith return 74*525d6f2eSBarry Smith 75*525d6f2eSBarry Smith @property 76*525d6f2eSBarry Smith def verbose(self): 77*525d6f2eSBarry Smith '''The verbosity level''' 78*525d6f2eSBarry Smith return self.argDB['verbose'] 79*525d6f2eSBarry Smith 80*525d6f2eSBarry Smith @property 81*525d6f2eSBarry Smith def dryRun(self): 82*525d6f2eSBarry Smith '''Flag for only output of what would be run''' 83*525d6f2eSBarry Smith return self.argDB['dryRun'] 84*525d6f2eSBarry Smith 85*525d6f2eSBarry Smith def getPackageInfo(self): 86*525d6f2eSBarry Smith packageIncludes = [] 87*525d6f2eSBarry Smith packageLibs = [] 88*525d6f2eSBarry Smith for p in self.framework.packages: 89*525d6f2eSBarry Smith # Could put on compile line, self.addDefine('HAVE_'+i.PACKAGE, 1) 90*525d6f2eSBarry Smith if hasattr(p, 'lib'): 91*525d6f2eSBarry Smith if not isinstance(p.lib, list): 92*525d6f2eSBarry Smith packageLibs.append(p.lib) 93*525d6f2eSBarry Smith else: 94*525d6f2eSBarry Smith packageLibs.extend(p.lib) 95*525d6f2eSBarry Smith if hasattr(p, 'include'): 96*525d6f2eSBarry Smith if not isinstance(p.include, list): 97*525d6f2eSBarry Smith packageIncludes.append(p.include) 98*525d6f2eSBarry Smith else: 99*525d6f2eSBarry Smith packageIncludes.extend(p.include) 100*525d6f2eSBarry Smith packageLibs = self.libraries.toStringNoDupes(packageLibs+self.libraries.math) 101*525d6f2eSBarry Smith packageIncludes = self.headers.toStringNoDupes(packageIncludes) 102*525d6f2eSBarry Smith return packageIncludes, packageLibs 103*525d6f2eSBarry Smith 104*525d6f2eSBarry Smith def buildDir(self, dirname): 105*525d6f2eSBarry Smith ''' This is run in a PETSc source directory''' 106*525d6f2eSBarry Smith if self.verbose: print 'Entering '+dirname 107*525d6f2eSBarry Smith os.chdir(dirname) 108*525d6f2eSBarry Smith l = len(os.environ['PETSC_DIR']) 109*525d6f2eSBarry Smith basedir = os.path.join(os.environ['PETSC_DIR'],os.environ['PETSC_ARCH'],'xcode-links') 110*525d6f2eSBarry Smith #newdirname = os.path.join(basedir,dirname[l+1:]) 111*525d6f2eSBarry Smith #os.mkdir(newdirname) 112*525d6f2eSBarry Smith 113*525d6f2eSBarry Smith 114*525d6f2eSBarry Smith # Get list of source files in the directory 115*525d6f2eSBarry Smith cnames = [] 116*525d6f2eSBarry Smith onames = [] 117*525d6f2eSBarry Smith fnames = [] 118*525d6f2eSBarry Smith hnames = [] 119*525d6f2eSBarry Smith for f in os.listdir(dirname): 120*525d6f2eSBarry Smith ext = os.path.splitext(f)[1] 121*525d6f2eSBarry Smith if ext == '.c': 122*525d6f2eSBarry Smith cnames.append(f) 123*525d6f2eSBarry Smith onames.append(f.replace('.c', '.o')) 124*525d6f2eSBarry Smith if ext == '.h': 125*525d6f2eSBarry Smith hnames.append(f) 126*525d6f2eSBarry Smith if cnames: 127*525d6f2eSBarry Smith if self.verbose: print 'Linking C files',cnames 128*525d6f2eSBarry Smith for i in cnames: 129*525d6f2eSBarry Smith j = i[l+1:] 130*525d6f2eSBarry Smith if not os.path.islink(os.path.join(basedir,i)): 131*525d6f2eSBarry Smith os.symlink(os.path.join(dirname,i),os.path.join(basedir,i)) 132*525d6f2eSBarry Smith # do not need to link these because xcode project points to original source code directory 133*525d6f2eSBarry Smith #if hnames: 134*525d6f2eSBarry Smith # if self.verbose: print 'Linking h files',hnames 135*525d6f2eSBarry Smith # for i in hnames: 136*525d6f2eSBarry Smith # if not os.path.islink(os.path.join(basedir,i)): 137*525d6f2eSBarry Smith # os.symlink(os.path.join(dirname,i),os.path.join(basedir,i)) 138*525d6f2eSBarry Smith return 139*525d6f2eSBarry Smith 140*525d6f2eSBarry Smith def checkDir(self, dirname): 141*525d6f2eSBarry Smith '''Checks whether we should recurse into this directory 142*525d6f2eSBarry Smith - Excludes projects directory 143*525d6f2eSBarry Smith - Excludes examples directory 144*525d6f2eSBarry Smith - Excludes contrib directory 145*525d6f2eSBarry Smith - Excludes tutorials directory 146*525d6f2eSBarry Smith - Excludes benchmarks directory 147*525d6f2eSBarry Smith - Checks whether fortran bindings are necessary 148*525d6f2eSBarry Smith - Checks makefile to see if compiler is allowed to visit this directory for this configuration''' 149*525d6f2eSBarry Smith# print self.functions.functions 150*525d6f2eSBarry Smith# print self.base.defines 151*525d6f2eSBarry Smith base = os.path.basename(dirname) 152*525d6f2eSBarry Smith 153*525d6f2eSBarry Smith if base == 'examples': return False 154*525d6f2eSBarry Smith if base == 'projects': return False 155*525d6f2eSBarry Smith if not hasattr(self.compilers, 'FC'): 156*525d6f2eSBarry Smith if base.startswith('ftn-') or base.startswith('f90-'): return False 157*525d6f2eSBarry Smith if base == 'contrib': return False 158*525d6f2eSBarry Smith if base == 'tutorials': return False 159*525d6f2eSBarry Smith if base == 'benchmarks': return False 160*525d6f2eSBarry Smith if base == 'xcode': return False 161*525d6f2eSBarry Smith if base.startswith('arch-'): return False 162*525d6f2eSBarry Smith 163*525d6f2eSBarry Smith import re 164*525d6f2eSBarry Smith reg = re.compile(' [ ]*') 165*525d6f2eSBarry Smith fname = os.path.join(dirname, 'makefile') 166*525d6f2eSBarry Smith if not os.path.isfile(fname): 167*525d6f2eSBarry Smith if os.path.isfile(os.path.join(dirname, 'Makefile')): print 'ERROR: Change Makefile to makefile in',dirname 168*525d6f2eSBarry Smith return False 169*525d6f2eSBarry Smith fd = open(fname) 170*525d6f2eSBarry Smith text = fd.readline() 171*525d6f2eSBarry Smith while text: 172*525d6f2eSBarry Smith if text.startswith('#requires'): 173*525d6f2eSBarry Smith text = text[9:-1].strip() 174*525d6f2eSBarry Smith text = reg.sub(' ',text) 175*525d6f2eSBarry Smith rtype = text.split(' ')[0] 176*525d6f2eSBarry Smith rvalue = text.split(' ')[1] 177*525d6f2eSBarry Smith 178*525d6f2eSBarry Smith if rvalue == "'"+'PETSC_HAVE_FORTRAN'+"'" or rvalue == "'"+'PETSC_USING_F90'+"'" or rvalue == "'"+'PETSC_USING_F2003'+"'": 179*525d6f2eSBarry Smith if not hasattr(self.compilers, 'FC'): 180*525d6f2eSBarry Smith if self.verbose: print 'Rejecting',dirname,'because fortran is not being used' 181*525d6f2eSBarry Smith return 0 182*525d6f2eSBarry Smith elif rvalue == "'"+'PETSC_USE_LOG'+"'": 183*525d6f2eSBarry Smith if not self.libraryOptions.useLog: 184*525d6f2eSBarry Smith if self.verbose: print 'Rejecting',dirname,'because logging is turned off' 185*525d6f2eSBarry Smith return 0 186*525d6f2eSBarry Smith elif rvalue == "'"+'PETSC_USE_FORTRAN_KERNELS'+"'": 187*525d6f2eSBarry Smith if not self.libraryOptions.useFortranKernels: 188*525d6f2eSBarry Smith if self.verbose: print 'Rejecting',dirname,'because fortran kernels are turned off' 189*525d6f2eSBarry Smith return 0 190*525d6f2eSBarry Smith elif rtype == 'scalar' and not self.scalarType.scalartype == rvalue: 191*525d6f2eSBarry Smith if self.verbose: print 'Rejecting',dirname,'because scalar type '+self.scalarType.scalartype+' is not '+rvalue 192*525d6f2eSBarry Smith return 0 193*525d6f2eSBarry Smith elif rtype == 'language': 194*525d6f2eSBarry Smith if rvalue == 'CXXONLY' and self.languages.clanguage == 'C': 195*525d6f2eSBarry Smith if self.verbose: print 'Rejecting',dirname,'because language is '+self.languages.clanguage+' is not C++' 196*525d6f2eSBarry Smith return 0 197*525d6f2eSBarry Smith elif rtype == 'precision' and not rvalue == self.scalarType.precision: 198*525d6f2eSBarry Smith if self.verbose: print 'Rejecting',dirname,'because precision '+self.scalarType.precision+' is not '+rvalue 199*525d6f2eSBarry Smith return 0 200*525d6f2eSBarry Smith elif rtype == 'package': 201*525d6f2eSBarry Smith found = 0 202*525d6f2eSBarry Smith if self.mpi.usingMPIUni: 203*525d6f2eSBarry Smith pname = 'PETSC_HAVE_MPIUNI' 204*525d6f2eSBarry Smith pname = "'"+pname+"'" 205*525d6f2eSBarry Smith if pname == rvalue: found = 1 206*525d6f2eSBarry Smith for i in self.framework.packages: 207*525d6f2eSBarry Smith pname = 'PETSC_HAVE_'+i.PACKAGE 208*525d6f2eSBarry Smith pname = "'"+pname+"'" 209*525d6f2eSBarry Smith if pname == rvalue: found = 1 210*525d6f2eSBarry Smith if not found: 211*525d6f2eSBarry Smith if self.verbose: print 'Rejecting',dirname,'because package '+rvalue+' does not exist' 212*525d6f2eSBarry Smith return 0 213*525d6f2eSBarry Smith elif rtype == 'define': 214*525d6f2eSBarry Smith found = 0 215*525d6f2eSBarry Smith for i in self.base.defines: 216*525d6f2eSBarry Smith pname = 'PETSC_'+i.upper() 217*525d6f2eSBarry Smith pname = "'"+pname+"'" 218*525d6f2eSBarry Smith if pname == rvalue: found = 1 219*525d6f2eSBarry Smith if not found: 220*525d6f2eSBarry Smith if self.verbose: print 'Rejecting',dirname,'because define '+rvalue+' does not exist' 221*525d6f2eSBarry Smith return 0 222*525d6f2eSBarry Smith elif rtype == 'function': 223*525d6f2eSBarry Smith found = 0 224*525d6f2eSBarry Smith for i in self.functions.functions: 225*525d6f2eSBarry Smith pname = 'PETSC_HAVE_'+i.upper() 226*525d6f2eSBarry Smith pname = "'"+pname+"'" 227*525d6f2eSBarry Smith# print pname 228*525d6f2eSBarry Smith# print rvalue 229*525d6f2eSBarry Smith if pname == rvalue: found = 1 230*525d6f2eSBarry Smith if not found: 231*525d6f2eSBarry Smith if self.verbose: print 'Rejecting',dirname,'because function '+rvalue+' does not exist' 232*525d6f2eSBarry Smith return 0 233*525d6f2eSBarry Smith 234*525d6f2eSBarry Smith text = fd.readline() 235*525d6f2eSBarry Smith fd.close() 236*525d6f2eSBarry Smith return True 237*525d6f2eSBarry Smith 238*525d6f2eSBarry Smith def buildAll(self, rootDir = None): 239*525d6f2eSBarry Smith import shutil 240*525d6f2eSBarry Smith self.setup() 241*525d6f2eSBarry Smith if rootDir is None: 242*525d6f2eSBarry Smith rootDir = self.argDB['rootDir'] 243*525d6f2eSBarry Smith if not self.checkDir(rootDir): 244*525d6f2eSBarry Smith print 'Nothing to be done' 245*525d6f2eSBarry Smith if rootDir == os.environ['PETSC_DIR']: 246*525d6f2eSBarry Smith basedir = os.path.join(self.petscdir.dir, self.arch.arch, 'xcode-links') 247*525d6f2eSBarry Smith if os.path.isdir(basedir): 248*525d6f2eSBarry Smith if self.verbose: print 'Removing '+basedir 249*525d6f2eSBarry Smith shutil.rmtree(basedir) 250*525d6f2eSBarry Smith os.mkdir(basedir) 251*525d6f2eSBarry Smith for root, dirs, files in os.walk(rootDir): 252*525d6f2eSBarry Smith self.buildDir(root) 253*525d6f2eSBarry Smith for badDir in [d for d in dirs if not self.checkDir(os.path.join(root, d))]: 254*525d6f2eSBarry Smith dirs.remove(badDir) 255*525d6f2eSBarry Smith 256*525d6f2eSBarry Smith print 'In Xcode mouse click on xcode-links and the delete key, then' 257*525d6f2eSBarry Smith print 'control mouse click on "Other Sources" and select "Add files to PETSc ...", then' 258*525d6f2eSBarry Smith print 'in the finder window locate ${PETSC_DIR}/arch-ios/xcode-links and select it. Now' 259*525d6f2eSBarry Smith print 'exit Xcode' 260*525d6f2eSBarry Smith 261*525d6f2eSBarry Smith try: 262*525d6f2eSBarry Smith import subprocess 263*525d6f2eSBarry Smith subprocess.call('cd '+os.path.join(os.environ['PETSC_DIR'],'systems','Apple','iOS','PETSc')+';open -W PETSc.xcodeproj', shell=True) 264*525d6f2eSBarry Smith except RuntimeError, e: 265*525d6f2eSBarry Smith raise RuntimeError('Error opening xcode project '+str(e)) 266*525d6f2eSBarry Smith 267*525d6f2eSBarry Smith 268*525d6f2eSBarry Smith sdk = ' -sdk iphonesimulator5.1 ' 269*525d6f2eSBarry Smith destination = 'iphonesimulator' 270*525d6f2eSBarry Smith debug = 'Debug' 271*525d6f2eSBarry Smith debugdir = 'Debug-'+destination 272*525d6f2eSBarry Smith if not self.compilerFlags.debugging: 273*525d6f2eSBarry Smith debug = 'Release' 274*525d6f2eSBarry Smith debugdir = 'Release-'+destination 275*525d6f2eSBarry Smith try: 276*525d6f2eSBarry 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) 277*525d6f2eSBarry Smith except RuntimeError, e: 278*525d6f2eSBarry Smith raise RuntimeError('Error making iPhone/iPad version of PETSc libraries: '+str(e)) 279*525d6f2eSBarry Smith 280*525d6f2eSBarry Smith liblocation = os.path.join(os.environ['PETSC_DIR'],'systems','Apple','iOS','PETSc','build',debugdir,'libPETSc.a') 281*525d6f2eSBarry Smith if not os.path.exists(liblocation): 282*525d6f2eSBarry Smith raise RuntimeError('Error library '+liblocation+' not created') 283*525d6f2eSBarry Smith try: 284*525d6f2eSBarry 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) 285*525d6f2eSBarry Smith except RuntimeError, e: 286*525d6f2eSBarry Smith raise RuntimeError('Error copying iPhone/iPad version of PETSc libraries: '+str(e)) 287*525d6f2eSBarry Smith 288*525d6f2eSBarry Smith return 289*525d6f2eSBarry Smith 290*525d6f2eSBarry Smithdef noCheckCommand(command, status, output, error): 291*525d6f2eSBarry Smith ''' Do no check result''' 292*525d6f2eSBarry Smith return 293*525d6f2eSBarry Smith noCheckCommand = staticmethod(noCheckCommand) 294*525d6f2eSBarry Smith 295*525d6f2eSBarry Smithif __name__ == '__main__': 296*525d6f2eSBarry Smith PETScMaker().buildAll() 297