1#!/usr/bin/env python3 2from __future__ import print_function 3import os, re, shutil, sys 4import sysconfig 5 6if 'PETSC_DIR' in os.environ: 7 PETSC_DIR = os.environ['PETSC_DIR'] 8else: 9 fd = open(os.path.join('lib','petsc','conf','petscvariables')) 10 a = fd.readline() 11 a = fd.readline() 12 PETSC_DIR = a.split('=')[1][0:-1] 13 fd.close() 14 15if 'PETSC_ARCH' in os.environ: 16 PETSC_ARCH = os.environ['PETSC_ARCH'] 17else: 18 fd = open(os.path.join('lib','petsc','conf','petscvariables')) 19 a = fd.readline() 20 PETSC_ARCH = a.split('=')[1][0:-1] 21 fd.close() 22 23print('*** Using PETSC_DIR='+PETSC_DIR+' PETSC_ARCH='+PETSC_ARCH+' ***') 24sys.path.insert(0, os.path.join(PETSC_DIR, 'config')) 25sys.path.insert(0, os.path.join(PETSC_DIR, 'config', 'BuildSystem')) 26 27import script 28 29try: 30 WindowsError 31except NameError: 32 WindowsError = None 33 34class Installer(script.Script): 35 def __init__(self, clArgs = None): 36 import RDict 37 argDB = RDict.RDict(None, None, 0, 0, readonly = True) 38 argDB.saveFilename = os.path.join(PETSC_DIR, PETSC_ARCH, 'lib','petsc','conf', 'RDict.db') 39 argDB.load() 40 script.Script.__init__(self, argDB = argDB) 41 if not clArgs is None: self.clArgs = clArgs 42 self.copies = [] 43 return 44 45 def setupHelp(self, help): 46 import nargs 47 script.Script.setupHelp(self, help) 48 help.addArgument('Installer', '-destDir=<path>', nargs.Arg(None, '', 'Destination Directory for install')) 49 help.addArgument('Installer', '-no-examples', nargs.Arg(None, '', 'Skip installing examples')) 50 return 51 52 53 def setupModules(self): 54 self.setCompilers = self.framework.require('config.setCompilers', None) 55 self.arch = self.framework.require('PETSc.options.arch', None) 56 self.petscdir = self.framework.require('PETSc.options.petscdir', None) 57 self.compilers = self.framework.require('config.compilers', None) 58 self.mpi = self.framework.require('config.packages.MPI', None) 59 return 60 61 def setup(self): 62 script.Script.setup(self) 63 self.framework = self.loadConfigure() 64 self.setupModules() 65 return 66 67 def setupDirectories(self): 68 self.rootDir = self.petscdir.dir 69 self.installDir = os.path.abspath(os.path.expanduser(self.framework.argDB['prefix'])) 70 self.destDir = os.path.abspath(self.argDB['destDir']+self.installDir) 71 self.arch = self.arch.arch 72 self.archDir = os.path.join(self.rootDir, self.arch) 73 self.rootIncludeDir = os.path.join(self.rootDir, 'include') 74 self.archIncludeDir = os.path.join(self.rootDir, self.arch, 'include') 75 self.rootConfDir = os.path.join(self.rootDir, 'lib','petsc','conf') 76 self.archConfDir = os.path.join(self.rootDir, self.arch, 'lib','petsc','conf') 77 self.rootBinDir = os.path.join(self.rootDir, 'lib','petsc','bin') 78 self.archBinDir = os.path.join(self.rootDir, self.arch, 'bin') 79 self.archLibDir = os.path.join(self.rootDir, self.arch, 'lib') 80 self.destIncludeDir = os.path.join(self.destDir, 'include') 81 self.destConfDir = os.path.join(self.destDir, 'lib','petsc','conf') 82 self.destLibDir = os.path.join(self.destDir, 'lib') 83 self.destBinDir = os.path.join(self.destDir, 'lib','petsc','bin') 84 self.installIncludeDir = os.path.join(self.installDir, 'include') 85 self.installLibDir = os.path.join(self.installDir, 'lib') 86 self.installBinDir = os.path.join(self.installDir, 'lib','petsc','bin') 87 self.rootShareDir = os.path.join(self.rootDir, 'share') 88 self.destShareDir = os.path.join(self.destDir, 'share') 89 self.rootSrcDir = os.path.join(self.rootDir, 'src') 90 91 self.ranlib = self.compilers.RANLIB 92 self.arLibSuffix = self.compilers.AR_LIB_SUFFIX 93 return 94 95 def checkPrefix(self): 96 if not self.installDir: 97 print('********************************************************************') 98 print('PETSc is built without prefix option. So "make install" is not appropriate.') 99 print('If you need a prefix install of PETSc - rerun configure with --prefix option.') 100 print('********************************************************************') 101 sys.exit(1) 102 return 103 104 def checkDestdir(self): 105 if os.path.exists(self.destDir): 106 if os.path.samefile(self.destDir, self.rootDir): 107 print('********************************************************************') 108 print('Incorrect prefix usage. Specified destDir same as current PETSC_DIR') 109 print('********************************************************************') 110 sys.exit(1) 111 if os.path.samefile(self.destDir, os.path.join(self.rootDir,self.arch)): 112 print('********************************************************************') 113 print('Incorrect prefix usage. Specified destDir same as current PETSC_DIR/PETSC_ARCH') 114 print('********************************************************************') 115 sys.exit(1) 116 if not os.path.isdir(os.path.realpath(self.destDir)): 117 print('********************************************************************') 118 print('Specified destDir', self.destDir, 'is not a directory. Cannot proceed!') 119 print('********************************************************************') 120 sys.exit(1) 121 if not os.access(self.destDir, os.W_OK): 122 print('********************************************************************') 123 print('Unable to write to ', self.destDir, 'Perhaps you need to do "sudo make install"') 124 print('********************************************************************') 125 sys.exit(1) 126 return 127 128 def setupBuild(self): 129 self.using_build_backend = any( 130 os.environ.get(prefix + '_BUILD_BACKEND') 131 for prefix in ('_PYPROJECT_HOOKS', 'PEP517') 132 ) 133 self.relocate_py_env = os.environ.get('CIBUILDWHEEL', '0') == '1' 134 135 def copyfile(self, src, dst, symlinks = False, copyFunc = shutil.copy2): 136 """Copies a single file """ 137 copies = [] 138 errors = [] 139 if not os.path.exists(dst): 140 os.makedirs(dst) 141 elif not os.path.isdir(dst): 142 raise shutil.Error('Destination is not a directory') 143 srcname = src 144 dstname = os.path.join(dst, os.path.basename(src)) 145 try: 146 if symlinks and os.path.islink(srcname): 147 linkto = os.readlink(srcname) 148 os.symlink(linkto, dstname) 149 else: 150 copyFunc(srcname, dstname) 151 copies.append((srcname, dstname)) 152 except (IOError, os.error) as why: 153 errors.append((srcname, dstname, str(why))) 154 except shutil.Error as err: 155 errors.append((srcname,dstname,str(err.args[0]))) 156 if errors: 157 raise shutil.Error(errors) 158 return copies 159 160 def fixExamplesMakefile(self, src): 161 '''Change ././${PETSC_ARCH} in makefile in root PETSc directory with ${PETSC_DIR}''' 162 lines = [] 163 oldFile = open(src, 'r') 164 alllines=oldFile.read() 165 oldFile.close() 166 newlines=alllines.split('\n')[0]+'\n' # Firstline 167 # Hardcode PETSC_DIR and PETSC_ARCH to avoid users doing the wrong thing 168 newlines+='PETSC_DIR='+self.installDir+'\n' 169 newlines+='PETSC_ARCH=\n' 170 for line in alllines.split('\n')[1:]: 171 if line.startswith('TESTLOGFILE'): 172 newlines+='TESTLOGFILE = $(TESTDIR)/examples-install.log\n' 173 elif line.startswith('CONFIGDIR'): 174 newlines+='CONFIGDIR:=$(PETSC_DIR)/$(PETSC_ARCH)/share/petsc/examples/config\n' 175 elif line.startswith('$(generatedtest)') and 'petscvariables' in line: 176 newlines+='all: test\n\n'+line+'\n' 177 else: 178 newlines+=line+'\n' 179 newFile = open(src, 'w') 180 newFile.write(newlines) 181 newFile.close() 182 return 183 184 def copyConfig(self, src, dst): 185 """Copy configuration/testing files 186 """ 187 if not os.path.isdir(dst): 188 raise shutil.Error('Destination is not a directory') 189 190 self.copies.extend(self.copyfile('gmakefile.test',dst)) 191 newConfigDir=os.path.join(dst,'config') # Am not renaming at present 192 if not os.path.isdir(newConfigDir): os.mkdir(newConfigDir) 193 testConfFiles="gmakegentest.py gmakegen.py testparse.py example_template.py".split() 194 testConfFiles+="petsc_harness.sh report_tests.py query_tests.py".split() 195 for tf in testConfFiles: 196 self.copies.extend(self.copyfile(os.path.join('config',tf),newConfigDir)) 197 return 198 199 def copyExamples(self, src, dst): 200 """copy the examples directories 201 """ 202 for root, dirs, files in os.walk(src, topdown=False): 203 if os.path.basename(root) not in ("tests", "tutorials"): continue 204 self.copies.extend(self.copytree(root, root.replace(src,dst))) 205 return 206 207 def copytree(self, src, dst, symlinks = False, copyFunc = shutil.copy2, exclude = [], exclude_ext= ['.DSYM','.o','.pyc'], recurse = 1): 208 """Recursively copy a directory tree using copyFunc, which defaults to shutil.copy2(). 209 210 The copyFunc() you provide is only used on the top level, lower levels always use shutil.copy2 211 212 The destination directory must not already exist. 213 If exception(s) occur, an shutil.Error is raised with a list of reasons. 214 215 If the optional symlinks flag is true, symbolic links in the 216 source tree result in symbolic links in the destination tree; if 217 it is false, the contents of the files pointed to by symbolic 218 links are copied. 219 """ 220 copies = [] 221 names = os.listdir(src) 222 if not os.path.exists(dst): 223 os.makedirs(dst) 224 elif not os.path.isdir(dst): 225 raise shutil.Error('Destination is not a directory') 226 errors = [] 227 srclinks = [] 228 dstlinks = [] 229 for name in names: 230 srcname = os.path.join(src, name) 231 dstname = os.path.join(dst, name) 232 try: 233 if symlinks and os.path.islink(srcname): 234 linkto = os.readlink(srcname) 235 os.symlink(linkto, dstname) 236 elif os.path.isdir(srcname) and recurse and not os.path.basename(srcname) in exclude: 237 copies.extend(self.copytree(srcname, dstname, symlinks,exclude = exclude, exclude_ext = exclude_ext)) 238 elif os.path.isfile(srcname) and not os.path.basename(srcname) in exclude and os.path.splitext(name)[1] not in exclude_ext : 239 if os.path.islink(srcname): 240 srclinks.append(srcname) 241 dstlinks.append(dstname) 242 else: 243 copyFunc(srcname, dstname) 244 copies.append((srcname, dstname)) 245 # XXX What about devices, sockets etc.? 246 except (IOError, os.error) as why: 247 errors.append((srcname, dstname, str(why))) 248 # catch the Error from the recursive copytree so that we can 249 # continue with other files 250 except shutil.Error as err: 251 errors.append((srcname,dstname,str(err.args[0]))) 252 for srcname, dstname in zip(srclinks, dstlinks): 253 try: 254 copyFunc(srcname, dstname) 255 copies.append((srcname, dstname)) 256 except (IOError, os.error) as why: 257 errors.append((srcname, dstname, str(why))) 258 # catch the Error from the recursive copytree so that we can 259 # continue with other files 260 except shutil.Error as err: 261 errors.append((srcname,dstname,str(err.args[0]))) 262 try: 263 shutil.copystat(src, dst) 264 except OSError as e: 265 if WindowsError is not None and isinstance(e, WindowsError): 266 # Copying file access times may fail on Windows 267 pass 268 else: 269 errors.append((src, dst, str(e))) 270 if errors: 271 raise shutil.Error(errors) 272 return copies 273 274 275 def fixConfFile(self, src): 276 lines = [] 277 oldFile = open(src, 'r') 278 for line in oldFile.readlines(): 279 if line.startswith('PETSC_CC_INCLUDES =') or line.startswith('PETSC_FC_INCLUDES ='): 280 continue 281 line = line.replace('PETSC_CC_INCLUDES_INSTALL', 'PETSC_CC_INCLUDES') 282 line = line.replace('PETSC_FC_INCLUDES_INSTALL', 'PETSC_FC_INCLUDES') 283 # remove PETSC_DIR/PETSC_ARCH variables from conf-makefiles. They are no longer necessary 284 line = line.replace('${PETSC_DIR}/${PETSC_ARCH}', self.installDir) 285 line = line.replace('PETSC_ARCH=${PETSC_ARCH}', '') 286 line = line.replace('${PETSC_DIR}', self.installDir) 287 # replace PETSC_DIR/PETSC_ARCH/lib (i.e., build location) with prefix/lib 288 line = line.replace(self.archLibDir,self.installLibDir) 289 # replace PETSC_DIR/lib/petsc/bin with prefix/lib/petsc/bin 290 line = line.replace(self.rootBinDir,self.destBinDir) 291 lines.append(line) 292 oldFile.close() 293 newFile = open(src, 'w') 294 newFile.write(''.join(lines)) 295 newFile.close() 296 return 297 298 def fixConf(self): 299 import shutil 300 for file in ['rules', 'rules_doc.mk', 'rules_util.mk', 'variables', 'petscrules', 'petscvariables']: 301 self.fixConfFile(os.path.join(self.destConfDir,file)) 302 return 303 304 def fixPythonWheel(self): 305 import glob 306 import shutil 307 # 308 for pattern in ( 309 self.destLibDir + '/*.a', 310 self.destLibDir + '/*.la', 311 self.destLibDir + '/pkgconfig', # TODO: keep? 312 self.destConfDir + '/configure-hash', 313 self.destConfDir + '/uninstall.py', 314 self.destConfDir + '/reconfigure-*.py', 315 self.destConfDir + '/pkg.conf.*', 316 self.destConfDir + '/pkg.git*.*', 317 self.destConfDir + '/modules', # TODO: keep? 318 self.destShareDir + '/*/examples/src/*', 319 self.destShareDir + '/*/datafiles', 320 ): 321 for pathname in glob.glob(pattern): 322 if os.path.isdir(pathname): 323 shutil.rmtree(pathname) 324 elif os.path.exists(pathname): 325 os.remove(pathname) 326 # 327 if self.relocate_py_env: 328 pydir = sys.prefix 329 pylibdir = os.path.join(pydir, 'lib') 330 pysitedir = sysconfig.get_paths()["platlib"] 331 # petsc is installed in site-packages 332 petscdir = os.path.join(pysitedir, 'petsc') 333 petsclibdir = os.path.join(petscdir, 'lib') 334 for filename in ( 335 self.destIncludeDir + '/petscconf.h', 336 self.destIncludeDir + '/petscconfiginfo.h', 337 self.destIncludeDir + '/petscmachineinfo.h', 338 self.destShareDir + '/petsc/examples/gmakefile.test', 339 self.destConfDir + '/rules', 340 self.destConfDir + '/rules_doc.mk', 341 self.destConfDir + '/rules_util.mk', 342 self.destConfDir + '/petscrules', 343 self.destConfDir + '/variables', 344 self.destConfDir + '/petscvariables', 345 ): 346 with open(filename, 'r') as oldFile: 347 contents = oldFile.read() 348 contents = contents.replace(self.installDir, '${PETSC_DIR}') 349 contents = contents.replace(self.rootDir, '${PETSC_DIR}') 350 if self.relocate_py_env: 351 pydir_from_petsc = os.path.relpath(pydir, petscdir) 352 contents = contents.replace(pydir, os.path.join('${PETSC_DIR}', pydir_from_petsc)) 353 contents = re.sub( 354 r'^(PYTHON(_EXE)?) = (.*)$', 355 r'\1 = python%d' % sys.version_info[0], 356 contents, flags=re.MULTILINE, 357 ) 358 with open(filename, 'w') as newFile: 359 newFile.write(contents) 360 # 361 def lsdir(dirname, *patterns): 362 return glob.glob(os.path.join(dirname, *patterns)) 363 def shell(*args): 364 return self.executeShellCommand(' '.join(args))[0] 365 libdir = os.path.join(self.installDir, 'lib') 366 if sys.platform == 'linux': 367 libraries = [ 368 lib for lib in lsdir(self.destLibDir, 'lib*.so*') 369 if not os.path.islink(lib) 370 ] 371 for shlib in libraries: 372 # fix shared library rpath 373 rpath = shell('patchelf', '--print-rpath', shlib) 374 rpath = rpath.split(os.path.pathsep) 375 if not self.relocate_py_env: 376 if libdir in rpath: 377 rpath.insert(0, '$ORIGIN') 378 while libdir in rpath: 379 rpath.remove(libdir) 380 else: 381 rpathold = rpath 382 rpath = [] 383 # strip all rpath info, except for libraries in Python 384 # sys prefix, site-packages, or petsc/lib 385 rpath.insert(0, '$ORIGIN') 386 for libdir in rpathold: 387 if libdir.startswith(pysitedir): 388 libdir_from_petsc = os.path.relpath(libdir, petsclibdir) 389 rpath.insert(0, os.path.join('$ORIGIN',libdir_from_petsc)) 390 pylibdir_from_petsc = os.path.relpath(pylibdir, petsclibdir) 391 rpath.insert(0, os.path.join('$ORIGIN',pylibdir_from_petsc)) 392 if rpath: 393 rpath = os.path.pathsep.join(rpath) 394 shell('patchelf', '--set-rpath', "'%s'" % rpath, shlib) 395 # fix shared library file and symlink 396 basename = os.path.basename(shlib) 397 libname, ext, _ = basename.partition('.so') 398 liblink = libname + ext 399 soname = shell('patchelf', '--print-soname', shlib) 400 for symlink in lsdir(self.destLibDir, liblink + '*'): 401 if os.path.islink(symlink): 402 os.unlink(symlink) 403 curdir = os.getcwd() 404 try: 405 os.chdir(os.path.dirname(shlib)) 406 if soname != basename: 407 os.rename(basename, soname) 408 if soname != liblink: 409 with open(liblink, 'w') as f: 410 f.write('INPUT(' + soname + ')\n') 411 finally: 412 os.chdir(curdir) 413 if sys.platform == 'darwin': 414 def otool(cmd, dylib): 415 pattern = r''' 416 ^\s+ cmd \s %s$\n 417 ^\s+ cmdsize \s \d+$\n 418 ^\s+ (?:name|path) \s (.*) \s \(offset \s \d+\)$ 419 ''' % cmd 420 return re.findall( 421 pattern, shell('otool', '-l', dylib), 422 flags=re.VERBOSE | re.MULTILINE, 423 ) 424 libraries = [ 425 lib for lib in lsdir(self.destLibDir, 'lib*.dylib') 426 if not os.path.islink(lib) 427 ] 428 for dylib in libraries: 429 install_name = otool('LC_ID_DYLIB', dylib)[0] 430 dependencies = otool('LC_LOAD_DYLIB', dylib) 431 runtime_path = otool('LC_RPATH', dylib) 432 # fix shared library install name and rpath 433 install_name = '@rpath/' + os.path.basename(install_name) 434 shell('install_name_tool', '-id', install_name, dylib) 435 if libdir in runtime_path: 436 shell('install_name_tool', '-delete_rpath', libdir, dylib) 437 for rpath in ('@loader_path',): 438 if rpath not in runtime_path: 439 shell('install_name_tool', '-add_rpath', rpath, dylib) 440 for dep in dependencies: 441 if os.path.dirname(dep) in (libdir,): 442 newid = '@rpath/' + os.path.basename(dep) 443 shell('install_name_tool', '-change', dep, newid, dylib) 444 # fix shared library file and symlink 445 basename = os.path.basename(dylib) 446 libname, ext = os.path.splitext(basename) 447 libname = libname.partition('.')[0] 448 liblink = libname + ext 449 dyname = os.path.basename(install_name) 450 for symlink in lsdir(self.destLibDir, libname + '*' + ext): 451 if os.path.islink(symlink): 452 os.unlink(symlink) 453 curdir = os.getcwd() 454 try: 455 os.chdir(os.path.dirname(dylib)) 456 if dyname != basename: 457 os.rename(basename, dyname) 458 if dyname != liblink: 459 os.symlink(dyname, liblink) 460 finally: 461 os.chdir(curdir) 462 # 463 return 464 465 def createUninstaller(self): 466 uninstallscript = os.path.join(self.destConfDir, 'uninstall.py') 467 f = open(uninstallscript, 'w') 468 # Could use the Python AST to do this 469 f.write('#!'+sys.executable+'\n') 470 f.write('import os\n') 471 f.write('prefixdir = "'+self.installDir+'"\n') 472 files = [dst.replace(self.destDir,self.installDir) for src, dst in self.copies] 473 files.append(uninstallscript.replace(self.destDir,self.installDir)) 474 f.write('files = '+repr(files)) 475 f.write(''' 476for file in files: 477 if os.path.exists(file) or os.path.islink(file): 478 os.remove(file) 479 dir = os.path.dirname(file) 480 while dir not in [os.path.dirname(prefixdir),'/']: 481 try: os.rmdir(dir) 482 except: break 483 dir = os.path.dirname(dir) 484''') 485 f.close() 486 os.chmod(uninstallscript,0o744) 487 return 488 489 def installIncludes(self): 490 exclude = ['makefile'] 491 if not hasattr(self.compilers.setCompilers, 'FC'): 492 exclude.append('finclude') 493 if not self.mpi.usingMPIUni: 494 exclude.append('mpiuni') 495 self.copies.extend(self.copytree(self.rootIncludeDir, self.destIncludeDir,exclude = exclude)) 496 self.copies.extend(self.copytree(self.archIncludeDir, self.destIncludeDir)) 497 return 498 499 def installConf(self): 500 self.copies.extend(self.copytree(self.rootConfDir, self.destConfDir, exclude = ['test.log'])) 501 self.copies.extend(self.copytree(self.archConfDir, self.destConfDir, exclude = ['sowing', 'configure.log.bkp','configure.log','make.log','gmake.log','test.log','error.log','memoryerror.log','files','testfiles','RDict.db'])) 502 return 503 504 def installBin(self): 505 exclude = ['bib2html','doc2lt','doctext','mapnames', 'pstogif','pstoxbm','tohtml'] 506 self.copies.extend(self.copytree(self.archBinDir, self.destBinDir, exclude = exclude )) 507 exclude = ['maint'] 508 if not self.mpi.usingMPIUni: 509 exclude.append('petsc-mpiexec.uni') 510 self.setCompilers.pushLanguage('C') 511 if self.setCompilers.getCompiler().find('win32fe') < 0: 512 exclude.append('win32fe') 513 self.setCompilers.popLanguage() 514 self.copies.extend(self.copytree(self.rootBinDir, self.destBinDir, exclude = exclude )) 515 return 516 517 def installShare(self): 518 if self.argDB['no-examples']: exclude = ['datafiles'] 519 else: exclude = [] 520 self.copies.extend(self.copytree(self.rootShareDir, self.destShareDir, exclude=exclude)) 521 examplesdir=os.path.join(self.destShareDir,'petsc','examples') 522 if os.path.exists(examplesdir): 523 shutil.rmtree(examplesdir) 524 os.mkdir(examplesdir) 525 os.mkdir(os.path.join(examplesdir,'src')) 526 self.copyConfig(self.rootDir,examplesdir) 527 if not self.argDB['no-examples']: 528 self.copyExamples(self.rootSrcDir,os.path.join(examplesdir,'src')) 529 self.fixExamplesMakefile(os.path.join(examplesdir,'gmakefile.test')) 530 return 531 532 def copyLib(self, src, dst): 533 '''Run ranlib on the destination library if it is an archive. Also run install_name_tool on dylib on Mac''' 534 # Symlinks (assumed local) are recreated at dst 535 if os.path.islink(src): 536 linkto = os.readlink(src) 537 try: 538 os.remove(dst) # In case it already exists 539 except OSError: 540 pass 541 os.symlink(linkto, dst) 542 return 543 shutil.copy2(src, dst) 544 if self.setCompilers.getCompiler().find('win32fe') < 0 and os.path.splitext(dst)[1] == '.'+self.arLibSuffix: 545 import shlex 546 self.executeShellCommand(shlex.split(self.ranlib) + [dst]) 547 if os.path.splitext(dst)[1] == '.dylib' and shutil.which('otool') and shutil.which('install_name_tool'): 548 [output,err,flg] = self.executeShellCommand(['otool', '-D', src]) 549 oldname = output[output.find("\n")+1:] 550 installName = oldname.replace(os.path.realpath(self.archDir), self.installDir) 551 self.executeShellCommand(['install_name_tool', '-id', installName, dst]) 552 # preserve the original timestamps - so that the .a vs .so time order is preserved 553 shutil.copystat(src,dst) 554 return 555 556 def installLib(self): 557 self.copies.extend(self.copytree(self.archLibDir, self.destLibDir, copyFunc = self.copyLib, exclude = ['.DIR'],recurse = 0)) 558 self.copies.extend(self.copytree(os.path.join(self.archLibDir,'pkgconfig'), os.path.join(self.destLibDir,'pkgconfig'), copyFunc = self.copyLib, exclude = ['.DIR'],recurse = 0)) 559 return 560 561 562 def outputInstallDone(self): 563 from config.packages.make import getMakeUserPath 564 print('''\ 565==================================== 566Install complete. 567Now to check if the libraries are working do (in current directory): 568%s PETSC_DIR=%s PETSC_ARCH="" check 569====================================\ 570''' % (getMakeUserPath(self.arch), self.installDir)) 571 return 572 573 def outputDestDirDone(self): 574 print('''\ 575==================================== 576Copy to DESTDIR %s is now complete. 577Before use - please copy/install over to specified prefix: %s 578====================================\ 579''' % (self.destDir,self.installDir)) 580 return 581 582 def runsetup(self): 583 self.setup() 584 self.setupDirectories() 585 self.setupBuild() 586 self.checkPrefix() 587 self.checkDestdir() 588 return 589 590 def runcopy(self): 591 if self.destDir == self.installDir: 592 print('*** Installing PETSc at prefix location:',self.destDir, ' ***') 593 else: 594 print('*** Copying PETSc to DESTDIR location:',self.destDir, ' ***') 595 if not os.path.exists(self.destDir): 596 try: 597 os.makedirs(self.destDir) 598 except: 599 print('********************************************************************') 600 print('Unable to create', self.destDir, 'Perhaps you need to do "sudo make install"') 601 print('********************************************************************') 602 sys.exit(1) 603 self.installIncludes() 604 self.installConf() 605 self.installBin() 606 self.installLib() 607 self.installShare() 608 self.createUninstaller() 609 return 610 611 def runfix(self): 612 self.fixConf() 613 if self.using_build_backend: 614 self.fixPythonWheel() 615 return 616 617 def rundone(self): 618 if self.destDir == self.installDir: 619 self.outputInstallDone() 620 else: 621 self.outputDestDirDone() 622 return 623 624 def run(self): 625 self.runsetup() 626 self.runcopy() 627 self.runfix() 628 self.rundone() 629 return 630 631if __name__ == '__main__': 632 Installer(sys.argv[1:]).run() 633 # temporary hack - delete log files created by BuildSystem - when 'sudo make install' is invoked 634 delfiles=['RDict.db','RDict.log','buildsystem.log','default.log','buildsystem.log.bkp','default.log.bkp'] 635 for delfile in delfiles: 636 if os.path.exists(delfile) and (os.stat(delfile).st_uid==0): 637 os.remove(delfile) 638