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