1import config.base 2 3import os 4import sys 5import re 6import pickle 7 8class Configure(config.base.Configure): 9 def __init__(self, framework): 10 config.base.Configure.__init__(self, framework) 11 self.headerPrefix = 'PETSC' 12 self.substPrefix = 'PETSC' 13 self.installed = 0 # 1 indicates that Configure itself has already compiled and installed PETSc 14 self.found = 1 15 return 16 17 def __str2__(self): 18 desc = [' Using GNU make: ' + self.make.make] 19 if self.defines.get('USE_COVERAGE'): 20 desc.extend([ 21 ' Code coverage: yes', 22 ' Using code coverage executable: {}'.format(self.getMakeMacro('PETSC_COVERAGE_EXEC')) 23 ]) 24 if not self.installed: 25 desc.append('xxx=========================================================================xxx') 26 desc.append(' Configure stage complete. Now build PETSc libraries with:') 27 desc.append(' %s PETSC_DIR=%s PETSC_ARCH=%s all' % (self.make.make_user, self.petscdir.dir, self.arch.arch)) 28 desc.append('xxx=========================================================================xxx') 29 else: 30 desc.append('xxx=========================================================================xxx') 31 desc.append(' Installation complete. You do not need to run make to compile or install the software') 32 desc.append('xxx=========================================================================xxx') 33 desc.append('') 34 return '\n'.join(desc) 35 36 def setupHelp(self, help): 37 import nargs 38 help.addArgument('PETSc', '-prefix=<dir>', nargs.Arg(None, '', 'Specifiy location to install PETSc (eg. /usr/local)')) 39 help.addArgument('PETSc', '-with-prefetch=<bool>', nargs.ArgBool(None, 1,'Enable checking for prefetch instructions')) 40 help.addArgument('Windows','-with-windows-graphics=<bool>', nargs.ArgBool(None, 1,'Enable check for Windows Graphics')) 41 help.addArgument('PETSc', '-with-default-arch=<bool>', nargs.ArgBool(None, 1, 'Allow using the last configured arch without setting PETSC_ARCH')) 42 help.addArgument('PETSc','-with-single-library=<bool>', nargs.ArgBool(None, 1,'Put all PETSc code into the single -lpetsc library')) 43 help.addArgument('PETSc','-with-fortran-bindings=<bool>', nargs.ArgBool(None, 1,'Build PETSc fortran bindings in the library and corresponding module files')) 44 help.addArgument('PETSc', '-with-ios=<bool>', nargs.ArgBool(None, 0, 'Build an iPhone/iPad version of PETSc library')) 45 help.addArgument('PETSc', '-with-display=<x11display>', nargs.Arg(None, '', 'Specifiy DISPLAY env variable for use with matlab test)')) 46 help.addArgument('PETSc', '-with-package-scripts=<pyscripts>', nargs.ArgFileList(None,None,'Specify configure package scripts for user provided packages')) 47 help.addArgument('PETSc', '-with-coverage=<bool>', nargs.ArgFuzzyBool(None, value=0, help='Enable or disable code-coverage collection')) 48 help.addArgument('PETSc', '-with-coverage-exec=<executable>', nargs.ArgExecutable(None, value='default-auto', mustExist=0, help='Name of executable to use for post-processing coverage data, e.g. \'gcov\' or \'llvm-cov\'. Pass \'auto\' to let configure infer from compiler')) 49 help.addArgument('PETSc', '-with-tau-perfstubs=<bool>', nargs.ArgBool(None, 1,'Enable TAU profiler stubs')) 50 help.addArgument('PETSc', '-with-strict-petscerrorcode=<bool>', nargs.ArgFuzzyBool(None, value=0, help='Enable strict PetscErrorCode mode, which enables additional compile-time checking for misuse of PetscErrorCode and error handling')) 51 return 52 53 def registerPythonFile(self,filename,directory): 54 ''' Add a python file to the framework and registers its headerprefix, ... externalpackagedir 55 directory is the directory where the file relative to the BuildSystem or config path in python notation with . ''' 56 (utilityName, ext) = os.path.splitext(filename) 57 if not utilityName.startswith('.') and not utilityName.startswith('#') and ext == '.py' and not utilityName == '__init__': 58 if directory: directory = directory+'.' 59 utilityObj = self.framework.require(directory+utilityName, self) 60 utilityObj.headerPrefix = self.headerPrefix 61 utilityObj.archProvider = self.arch 62 utilityObj.languageProvider = self.languages 63 utilityObj.installDirProvider = self.installdir 64 utilityObj.externalPackagesDirProvider = self.externalpackagesdir 65 utilityObj.precisionProvider = self.scalartypes 66 utilityObj.indexProvider = self.indexTypes 67 setattr(self, utilityName.lower(), utilityObj) 68 return utilityObj 69 return None 70 71 def setupDependencies(self, framework): 72 config.base.Configure.setupDependencies(self, framework) 73 self.programs = framework.require('config.programs', self) 74 self.setCompilers = framework.require('config.setCompilers', self) 75 self.compilerFlags = framework.require('config.compilerFlags', self) 76 self.compilers = framework.require('config.compilers', self) 77 self.arch = framework.require('PETSc.options.arch', self.setCompilers) 78 self.petscdir = framework.require('PETSc.options.petscdir', self.arch) 79 self.installdir = framework.require('PETSc.options.installDir', self) 80 self.dataFilesPath = framework.require('PETSc.options.dataFilesPath',self) 81 self.scalartypes = framework.require('PETSc.options.scalarTypes', self) 82 self.indexTypes = framework.require('PETSc.options.indexTypes', self) 83 self.languages = framework.require('PETSc.options.languages', self.setCompilers) 84 self.indexTypes = framework.require('PETSc.options.indexTypes', self.compilers) 85 self.types = framework.require('config.types', self) 86 self.headers = framework.require('config.headers', self) 87 self.functions = framework.require('config.functions', self) 88 self.libraries = framework.require('config.libraries', self) 89 self.atomics = framework.require('config.atomics', self) 90 self.make = framework.require('config.packages.make', self) 91 self.blasLapack = framework.require('config.packages.BlasLapack',self) 92 self.mpi = framework.require('config.packages.MPI', self) 93 self.fortran = framework.require('config.compilersFortran', self) 94 self.externalpackagesdir = framework.require('PETSc.options.externalpackagesdir',self) 95 96 for utility in sorted(os.listdir(os.path.join('config','PETSc','options'))): 97 self.registerPythonFile(utility,'PETSc.options') 98 99 for utility in sorted(os.listdir(os.path.join('config','BuildSystem','config','utilities'))): 100 self.registerPythonFile(utility,'config.utilities') 101 102 for package in sorted(os.listdir(os.path.join('config', 'BuildSystem', 'config', 'packages'))): 103 obj = self.registerPythonFile(package,'config.packages') 104 if obj: 105 obj.archProvider = self.framework.requireModule(obj.archProvider, obj) 106 obj.languageProvider = self.framework.requireModule(obj.languageProvider, obj) 107 obj.installDirProvider = self.framework.requireModule(obj.installDirProvider, obj) 108 obj.externalPackagesDirProvider = self.framework.requireModule(obj.externalPackagesDirProvider, obj) 109 obj.precisionProvider = self.framework.requireModule(obj.precisionProvider, obj) 110 obj.indexProvider = self.framework.requireModule(obj.indexProvider, obj) 111 112 # Force blaslapack and opencl to depend on scalarType so precision is set before BlasLapack is built 113 framework.require('PETSc.options.scalarTypes', self.f2cblaslapack) 114 framework.require('PETSc.options.scalarTypes', self.fblaslapack) 115 framework.require('PETSc.options.scalarTypes', self.blaslapack) 116 framework.require('PETSc.options.scalarTypes', self.opencl) 117 118 self.programs.headerPrefix = self.headerPrefix 119 self.setCompilers.headerPrefix = self.headerPrefix 120 self.compilers.headerPrefix = self.headerPrefix 121 self.fortran.headerPrefix = self.headerPrefix 122 self.types.headerPrefix = self.headerPrefix 123 self.headers.headerPrefix = self.headerPrefix 124 self.functions.headerPrefix = self.headerPrefix 125 self.libraries.headerPrefix = self.headerPrefix 126 127 # Register user provided package scripts 128 if 'with-package-scripts' in self.framework.argDB: 129 for script in self.framework.argDB['with-package-scripts']: 130 if os.path.splitext(script)[1] != '.py': 131 raise RuntimeError('Only python scripts compatible with configure package script format should be specified! Invalid option -with-package-scripts='+script) 132 self.framework.logPrint('User is registering a new package script: '+script) 133 dname,fname = os.path.split(script) 134 if dname: sys.path.append(dname) 135 self.registerPythonFile(fname,'') 136 137 # test for a variety of basic headers and functions 138 headersC = map(lambda name: name+'.h',['setjmp','dos','fcntl','float','io','malloc','pwd','strings', 139 'unistd','machine/endian','sys/param','sys/procfs','sys/resource', 140 'sys/systeminfo','sys/times','sys/utsname', 141 'sys/socket','sys/wait','netinet/in','netdb','direct','time','Ws2tcpip','sys/types', 142 'WindowsX','float','ieeefp','stdint','inttypes','immintrin']) 143 functions = ['access','_access','clock','drand48','getcwd','_getcwd','getdomainname','gethostname', 144 'getwd','posix_memalign','popen','PXFGETARG','rand','getpagesize', 145 'readlink','realpath','usleep','sleep','_sleep', 146 'uname','snprintf','_snprintf','lseek','_lseek','time','fork','stricmp', 147 'strcasecmp','bzero','dlopen','dlsym','dlclose','dlerror', 148 '_set_output_format','_mkdir','socket','gethostbyname','fpresetsticky', 149 'fpsetsticky','__gcov_dump'] 150 libraries = [(['fpe'],'handle_sigfpes')] 151 librariessock = [(['socket','nsl'],'socket')] 152 self.headers.headers.extend(headersC) 153 self.functions.functions.extend(functions) 154 self.libraries.libraries.extend(libraries) 155 if not hasattr(self,'socket'): 156 self.libraries.libraries.extend(librariessock) 157 return 158 159 def DumpPkgconfig(self, petsc_pc): 160 ''' Create a pkg-config file ''' 161 if not os.path.exists(os.path.join(self.petscdir.dir,self.arch.arch,'lib','pkgconfig')): 162 os.makedirs(os.path.join(self.petscdir.dir,self.arch.arch,'lib','pkgconfig')) 163 with open(os.path.join(self.petscdir.dir,self.arch.arch,'lib','pkgconfig',petsc_pc),'w') as fd: 164 cflags_inc = ['-I${includedir}'] 165 if self.framework.argDB['prefix']: 166 fd.write('prefix='+self.installdir.dir+'\n') 167 else: 168 fd.write('prefix='+os.path.join(self.petscdir.dir, self.arch.arch)+'\n') 169 cflags_inc.append('-I' + os.path.join(self.petscdir.dir, 'include')) 170 fd.write('exec_prefix=${prefix}\n') 171 fd.write('includedir=${prefix}/include\n') 172 fd.write('libdir=${prefix}/lib\n') 173 174 with self.setCompilers.Language('C'): 175 fd.write('ccompiler='+self.setCompilers.getCompiler()+'\n') 176 fd.write('cflags_extra='+self.setCompilers.getCompilerFlags().strip()+'\n') 177 fd.write('cflags_dep='+self.compilers.dependenciesGenerationFlag.get('C','')+'\n') 178 fd.write('ldflag_rpath='+self.setCompilers.CSharedLinkerFlag+'\n') 179 if hasattr(self.compilers, 'CXX'): 180 with self.setCompilers.Language('C++'): 181 fd.write('cxxcompiler='+self.setCompilers.getCompiler()+'\n') 182 fd.write('cxxflags_extra='+self.setCompilers.getCompilerFlags().strip()+'\n') 183 if hasattr(self.compilers, 'FC'): 184 with self.setCompilers.Language('FC'): 185 fd.write('fcompiler='+self.setCompilers.getCompiler()+'\n') 186 fd.write('fflags_extra='+self.setCompilers.getCompilerFlags().strip()+'\n') 187 if hasattr(self.compilers, 'CUDAC'): 188 with self.setCompilers.Language('CUDA'): 189 fd.write('cudacompiler='+self.setCompilers.getCompiler()+'\n') 190 fd.write('cudaflags_extra='+self.setCompilers.getCompilerFlags().strip()+'\n') 191 p = self.framework.require('config.packages.cuda') 192 fd.write('cudalib='+self.libraries.toStringNoDupes(p.lib)+'\n') 193 fd.write('cudainclude='+self.headers.toStringNoDupes(p.include)+'\n') 194 if hasattr(self.setCompilers,'CUDA_CXX'): 195 fd.write('cuda_cxx='+self.setCompilers.CUDA_CXX+'\n') 196 fd.write('cuda_cxxflags='+self.setCompilers.CUDA_CXXFLAGS+'\n') 197 198 fd.write('\n') 199 fd.write('Name: PETSc\n') 200 fd.write('Description: Library to solve ODEs and algebraic equations\n') 201 fd.write('Version: %s\n' % self.petscdir.version) 202 fd.write('Cflags: ' + ' '.join([self.setCompilers.CPPFLAGS] + cflags_inc) + '\n') 203 fd.write('Libs: '+self.libraries.toStringNoDupes(['-L${libdir}', self.petsclib], with_rpath=False)+'\n') 204 # Remove RPATH flags from library list. User can add them using 205 # pkg-config --variable=ldflag_rpath and pkg-config --libs-only-L 206 fd.write('Libs.private: '+self.libraries.toStringNoDupes([f for f in self.packagelibs+self.complibs if not f.startswith(self.setCompilers.CSharedLinkerFlag)], with_rpath=False)+'\n') 207 return 208 209 def DumpModule(self): 210 ''' Create a module file ''' 211 if not os.path.exists(os.path.join(self.petscdir.dir,self.arch.arch,'lib','petsc','conf','modules')): 212 os.makedirs(os.path.join(self.petscdir.dir,self.arch.arch,'lib','petsc','conf','modules')) 213 if not os.path.exists(os.path.join(self.petscdir.dir,self.arch.arch,'lib','petsc','conf','modules','petsc')): 214 os.makedirs(os.path.join(self.petscdir.dir,self.arch.arch,'lib','petsc','conf','modules','petsc')) 215 if self.framework.argDB['prefix']: 216 installdir = self.installdir.dir 217 installarch = '' 218 installpath = os.path.join(installdir,'bin') 219 else: 220 installdir = self.petscdir.dir 221 installarch = self.arch.arch 222 installpath = os.path.join(installdir,installarch,'bin')+':'+os.path.join(installdir,'bin') 223 fd = open(os.path.join(self.petscdir.dir,self.arch.arch,'lib','petsc','conf','modules','petsc',self.petscdir.version),'w') 224 fd.write('''\ 225#%%Module 226 227proc ModulesHelp { } { 228 puts stderr "This module sets the path and environment variables for petsc-%s" 229 puts stderr " see https://petsc.org/ for more information " 230 puts stderr "" 231} 232module-whatis "PETSc - Portable, Extensible Toolkit for Scientific Computation" 233 234set petsc_dir "%s" 235set petsc_arch "%s" 236 237setenv PETSC_ARCH "$petsc_arch" 238setenv PETSC_DIR "$petsc_dir" 239prepend-path PATH "%s" 240''' % (self.petscdir.version, installdir, installarch, installpath)) 241 fd.close() 242 return 243 244 def Dump(self): 245 ''' Actually put the values into the configuration files ''' 246 # eventually everything between -- should be gone 247 if self.mpi.usingMPIUni: 248 # 249 # Remove any MPI/MPICH include files that may have been put here by previous runs of ./configure 250 self.executeShellCommand('rm -rf '+os.path.join(self.petscdir.dir,self.arch.arch,'include','mpi*')+' '+os.path.join(self.petscdir.dir,self.arch.arch,'include','opa*'), log = self.log) 251 252 self.logPrintDivider() 253 # Test for compiler-specific macros that need to be defined. 254 if self.setCompilers.isCrayVector('CC', self.log): 255 self.addDefine('HAVE_CRAY_VECTOR','1') 256 257 if self.functions.haveFunction('gethostbyname') and self.functions.haveFunction('socket') and self.headers.haveHeader('netinet/in.h'): 258 self.addDefine('USE_SOCKET_VIEWER','1') 259 if self.checkCompile('#include <sys/socket.h>','setsockopt(0,SOL_SOCKET,SO_REUSEADDR,0,0)'): 260 self.addDefine('HAVE_SO_REUSEADDR','1') 261 262 self.logPrintDivider() 263 self.setCompilers.pushLanguage('C') 264 compiler = self.setCompilers.getCompiler() 265 if [s for s in ['mpicc','mpiicc'] if os.path.basename(compiler).find(s)>=0]: 266 try: 267 output = self.executeShellCommand(compiler + ' -show', log = self.log)[0] 268 compiler = output.split(' ')[0] 269 self.addDefine('MPICC_SHOW','"'+output.strip().replace('\n','\\\\n').replace('"','')+'"') 270 except: 271 self.addDefine('MPICC_SHOW','"Unavailable"') 272 else: 273 self.addDefine('MPICC_SHOW','"Unavailable"') 274 self.setCompilers.popLanguage() 275#----------------------------------------------------------------------------------------------------- 276 277 # Sometimes we need C compiler, even if built with C++ 278 self.setCompilers.pushLanguage('C') 279 # do not use getCompilerFlags() because that automatically includes the CPPFLAGS so one ends up with duplication flags in makefile usage 280 self.addMakeMacro('CC_FLAGS',self.setCompilers.CFLAGS) 281 self.setCompilers.popLanguage() 282 283 # And sometimes we need a C++ compiler even when PETSc is built with C 284 if hasattr(self.compilers, 'CXX'): 285 self.setCompilers.pushLanguage('Cxx') 286 self.addDefine('HAVE_CXX','1') 287 self.addMakeMacro('CXXPP_FLAGS',self.setCompilers.CXXPPFLAGS) 288 # do not use getCompilerFlags() because that automatically includes the CXXPPFLAGS so one ends up with duplication flags in makefile usage 289 self.addMakeMacro('CXX_FLAGS',self.setCompilers.CXXFLAGS+' '+self.setCompilers.CXX_CXXFLAGS) 290 cxx_linker = self.setCompilers.getLinker() 291 self.addMakeMacro('CXX_LINKER',cxx_linker) 292 self.addMakeMacro('CXX_LINKER_FLAGS',self.setCompilers.getLinkerFlags()) 293 self.setCompilers.popLanguage() 294 295 # C preprocessor values 296 self.addMakeMacro('CPP_FLAGS',self.setCompilers.CPPFLAGS) 297 298 # compiler values 299 self.setCompilers.pushLanguage(self.languages.clanguage) 300 self.addMakeMacro('PCC',self.setCompilers.getCompiler()) 301 # do not use getCompilerFlags() because that automatically includes the preprocessor flags so one ends up with duplication flags in makefile usage 302 if self.languages.clanguage == 'C': 303 self.addMakeMacro('PCC_FLAGS','$(CC_FLAGS)') 304 else: 305 self.addMakeMacro('PCC_FLAGS','$(CXX_FLAGS)') 306 self.setCompilers.popLanguage() 307 # .o or .obj 308 self.addMakeMacro('CC_SUFFIX','o') 309 310 # executable linker values 311 self.setCompilers.pushLanguage(self.languages.clanguage) 312 pcc_linker = self.setCompilers.getLinker() 313 self.addMakeMacro('PCC_LINKER',pcc_linker) 314 self.addMakeMacro('PCC_LINKER_FLAGS',self.setCompilers.getLinkerFlags()) 315 self.setCompilers.popLanguage() 316 # '' for Unix, .exe for Windows 317 self.addMakeMacro('CC_LINKER_SUFFIX','') 318 319 if hasattr(self.compilers, 'FC'): 320 if self.framework.argDB['with-fortran-bindings']: 321 if not self.fortran.fortranIsF90: 322 raise RuntimeError('Error! Fortran compiler "'+self.compilers.FC+'" does not support F90! PETSc fortran bindings require a F90 compiler') 323 self.addDefine('HAVE_FORTRAN','1') 324 self.setCompilers.pushLanguage('FC') 325 # need FPPFLAGS in config/setCompilers 326 self.addMakeMacro('FPP_FLAGS',self.setCompilers.FPPFLAGS) 327 328 # compiler values 329 self.addMakeMacro('FC_FLAGS',self.setCompilers.getCompilerFlags()) 330 self.setCompilers.popLanguage() 331 # .o or .obj 332 self.addMakeMacro('FC_SUFFIX','o') 333 334 # executable linker values 335 self.setCompilers.pushLanguage('FC') 336 self.addMakeMacro('FC_LINKER',self.setCompilers.getLinker()) 337 self.addMakeMacro('FC_LINKER_FLAGS',self.setCompilers.getLinkerFlags()) 338 self.setCompilers.popLanguage() 339 340 # F90 Modules 341 if self.setCompilers.fortranModuleIncludeFlag: 342 self.addMakeMacro('FC_MODULE_FLAG', self.setCompilers.fortranModuleIncludeFlag) 343 else: # for non-f90 compilers like g77 344 self.addMakeMacro('FC_MODULE_FLAG', '-I') 345 if self.setCompilers.fortranModuleIncludeFlag: 346 self.addMakeMacro('FC_MODULE_OUTPUT_FLAG', self.setCompilers.fortranModuleOutputFlag) 347 else: 348 self.addMakeMacro('FC','') 349 350 if hasattr(self.compilers, 'CUDAC'): 351 self.setCompilers.pushLanguage('CUDA') 352 self.addMakeMacro('CUDAC_FLAGS',self.setCompilers.getCompilerFlags()) 353 self.addMakeMacro('CUDAPP_FLAGS',self.setCompilers.CUDAPPFLAGS) 354 self.setCompilers.popLanguage() 355 356 if hasattr(self.compilers, 'HIPC'): 357 self.setCompilers.pushLanguage('HIP') 358 self.addMakeMacro('HIPC_FLAGS',self.setCompilers.getCompilerFlags()) 359 self.addMakeMacro('HIPPP_FLAGS',self.setCompilers.HIPPPFLAGS) 360 self.setCompilers.popLanguage() 361 362 if hasattr(self.compilers, 'SYCLC'): 363 self.setCompilers.pushLanguage('SYCL') 364 self.addMakeMacro('SYCLC_FLAGS',self.setCompilers.getCompilerFlags()) 365 self.addMakeMacro('SYCLPP_FLAGS',self.setCompilers.SYCLPPFLAGS) 366 self.setCompilers.popLanguage() 367 368 # shared library linker values 369 self.setCompilers.pushLanguage(self.languages.clanguage) 370 # need to fix BuildSystem to collect these separately 371 self.addMakeMacro('SL_LINKER',self.setCompilers.getLinker()) 372 self.addMakeMacro('SL_LINKER_FLAGS','${PCC_LINKER_FLAGS}') 373 self.setCompilers.popLanguage() 374 # One of 'a', 'so', 'lib', 'dll', 'dylib' (perhaps others also?) depending on the library generator and architecture 375 # Note: . is not included in this macro, consistent with AR_LIB_SUFFIX 376 if self.setCompilers.sharedLibraryExt == self.setCompilers.AR_LIB_SUFFIX: 377 self.addMakeMacro('SL_LINKER_SUFFIX', '') 378 self.addDefine('SLSUFFIX','""') 379 else: 380 self.addMakeMacro('SL_LINKER_SUFFIX', self.setCompilers.sharedLibraryExt) 381 self.addDefine('SLSUFFIX','"'+self.setCompilers.sharedLibraryExt+'"') 382 383 self.addMakeMacro('SL_LINKER_LIBS','${PETSC_EXTERNAL_LIB_BASIC}') 384 385#----------------------------------------------------------------------------------------------------- 386 387 # CONLY or CPP. We should change the PETSc makefiles to do this better 388 if self.languages.clanguage == 'C': lang = 'CONLY' 389 else: lang = 'CXXONLY' 390 self.addMakeMacro('PETSC_LANGUAGE',lang) 391 392 # real or complex 393 self.addMakeMacro('PETSC_SCALAR',self.scalartypes.scalartype) 394 # double or float 395 self.addMakeMacro('PETSC_PRECISION',self.scalartypes.precision) 396 397 if self.framework.argDB['with-batch']: 398 self.addMakeMacro('PETSC_WITH_BATCH','1') 399 400#----------------------------------------------------------------------------------------------------- 401 # print include and lib for makefiles 402 self.logPrintDivider() 403 self.framework.packages.reverse() 404 petscincludes = [os.path.join(self.petscdir.dir,'include'),os.path.join(self.petscdir.dir,self.arch.arch,'include')] 405 petscincludes_install = [os.path.join(self.installdir.dir, 'include')] if self.framework.argDB['prefix'] else petscincludes 406 includes = [] 407 self.packagelibs = [] 408 for i in self.framework.packages: 409 if not i.required: 410 if i.devicePackage: 411 self.addDefine('HAVE_DEVICE',1) 412 self.addDefine('HAVE_'+i.PACKAGE.replace('-','_'), 1) # ONLY list package if it is used directly by PETSc (and not only by another package) 413 if not isinstance(i.lib, list): 414 i.lib = [i.lib] 415 if i.linkedbypetsc: self.packagelibs.extend(i.lib) 416 self.addMakeMacro(i.PACKAGE.replace('-','_')+'_LIB', self.libraries.toStringNoDupes(i.lib)) 417 if hasattr(i,'include'): 418 if not isinstance(i.include,list): 419 i.include = [i.include] 420 includes.extend(i.include) 421 self.addMakeMacro(i.PACKAGE.replace('-','_')+'_INCLUDE',self.headers.toStringNoDupes(i.include)) 422 if self.framework.argDB['with-single-library']: 423 self.petsclib = '-lpetsc' 424 else: 425 self.petsclib = '-lpetscts -lpetscsnes -lpetscksp -lpetscdm -lpetscmat -lpetscvec -lpetscsys' 426 self.complibs = self.compilers.flibs+self.compilers.cxxlibs+self.compilers.LIBS.split() 427 self.PETSC_WITH_EXTERNAL_LIB = self.libraries.toStringNoDupes(['-L${PETSC_DIR}/${PETSC_ARCH}/lib', self.petsclib]+self.packagelibs+self.complibs) 428 self.PETSC_EXTERNAL_LIB_BASIC = self.libraries.toStringNoDupes(self.packagelibs+self.complibs) 429 430 self.addMakeMacro('PETSC_EXTERNAL_LIB_BASIC',self.PETSC_EXTERNAL_LIB_BASIC) 431 allincludes = petscincludes + includes 432 allincludes_install = petscincludes_install + includes 433 self.PETSC_CC_INCLUDES = self.headers.toStringNoDupes(allincludes) 434 self.PETSC_CC_INCLUDES_INSTALL = self.headers.toStringNoDupes(allincludes_install) 435 self.addMakeMacro('PETSC_CC_INCLUDES',self.PETSC_CC_INCLUDES) 436 self.addMakeMacro('PETSC_CC_INCLUDES_INSTALL', self.PETSC_CC_INCLUDES_INSTALL) 437 if hasattr(self.compilers, 'FC'): 438 def modinc(includes): 439 return includes if self.fortran.fortranIsF90 else [] 440 self.addMakeMacro('PETSC_FC_INCLUDES',self.headers.toStringNoDupes(allincludes,modinc(allincludes))) 441 self.addMakeMacro('PETSC_FC_INCLUDES_INSTALL',self.headers.toStringNoDupes(allincludes_install,modinc(allincludes_install))) 442 443 self.addDefine('LIB_DIR','"'+os.path.join(self.installdir.dir,'lib')+'"') 444 445 if self.framework.argDB['with-single-library']: 446 # overrides the values set in conf/variables 447 self.addMakeMacro('LIBNAME','${INSTALL_LIB_DIR}/libpetsc.${AR_LIB_SUFFIX}') 448 self.addMakeMacro('SHLIBS','libpetsc') 449 self.addMakeMacro('PETSC_LIB_BASIC','-lpetsc') 450 self.addMakeMacro('PETSC_KSP_LIB_BASIC','-lpetsc') 451 self.addMakeMacro('PETSC_TS_LIB_BASIC','-lpetsc') 452 self.addMakeMacro('PETSC_TAO_LIB_BASIC','-lpetsc') 453 self.addMakeMacro('PETSC_WITH_EXTERNAL_LIB',self.PETSC_WITH_EXTERNAL_LIB) 454 self.addDefine('USE_SINGLE_LIBRARY', '1') 455 if self.sharedlibraries.useShared: 456 self.addMakeMacro('PETSC_SYS_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}') 457 self.addMakeMacro('PETSC_VEC_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}') 458 self.addMakeMacro('PETSC_MAT_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}') 459 self.addMakeMacro('PETSC_DM_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}') 460 self.addMakeMacro('PETSC_KSP_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}') 461 self.addMakeMacro('PETSC_SNES_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}') 462 self.addMakeMacro('PETSC_TS_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}') 463 self.addMakeMacro('PETSC_TAO_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}') 464 self.addMakeMacro('PETSC_CHARACTERISTIC_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}') 465 self.addMakeMacro('PETSC_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}') 466 self.addMakeMacro('PETSC_CONTRIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}') 467 else: 468 self.addMakeMacro('PETSC_SYS_LIB','${PETSC_WITH_EXTERNAL_LIB}') 469 self.addMakeMacro('PETSC_VEC_LIB','${PETSC_WITH_EXTERNAL_LIB}') 470 self.addMakeMacro('PETSC_MAT_LIB','${PETSC_WITH_EXTERNAL_LIB}') 471 self.addMakeMacro('PETSC_DM_LIB','${PETSC_WITH_EXTERNAL_LIB}') 472 self.addMakeMacro('PETSC_KSP_LIB','${PETSC_WITH_EXTERNAL_LIB}') 473 self.addMakeMacro('PETSC_SNES_LIB','${PETSC_WITH_EXTERNAL_LIB}') 474 self.addMakeMacro('PETSC_TS_LIB','${PETSC_WITH_EXTERNAL_LIB}') 475 self.addMakeMacro('PETSC_TAO_LIB','${PETSC_WITH_EXTERNAL_LIB}') 476 self.addMakeMacro('PETSC_CHARACTERISTIC_LIB','${PETSC_WITH_EXTERNAL_LIB}') 477 self.addMakeMacro('PETSC_LIB','${PETSC_WITH_EXTERNAL_LIB}') 478 self.addMakeMacro('PETSC_CONTRIB','${PETSC_WITH_EXTERNAL_LIB}') 479 480 if not os.path.exists(os.path.join(self.petscdir.dir,self.arch.arch,'lib')): 481 os.makedirs(os.path.join(self.petscdir.dir,self.arch.arch,'lib')) 482 483# add a makefile endtry for display 484 if self.framework.argDB['with-display']: 485 self.addMakeMacro('DISPLAY',self.framework.argDB['with-display']) 486 487 # add a makefile entry for configure options 488 self.addMakeMacro('CONFIGURE_OPTIONS', self.framework.getOptionsString(['configModules', 'optionsModule']).replace('\"','\\"')) 489 490 if self.framework.argDB['with-tau-perfstubs']: 491 self.addDefine('HAVE_TAU_PERFSTUBS',1) 492 return 493 494 def dumpConfigInfo(self): 495 import time 496 fd = open(os.path.join(self.arch.arch,'include','petscconfiginfo.h'),'w') 497 fd.write('static const char *petscconfigureoptions = "'+self.framework.getOptionsString(['configModules', 'optionsModule']).replace('\"','\\"').replace('\\ ','\\\\ ')+'";\n') 498 fd.close() 499 return 500 501 def dumpMachineInfo(self): 502 import platform 503 import datetime 504 import time 505 import script 506 def escape(s): 507 return s.replace('"',r'\"').replace(r'\ ',r'\\ ') # novermin 508 fd = open(os.path.join(self.arch.arch,'include','petscmachineinfo.h'),'w') 509 fd.write('static const char *petscmachineinfo = \"\\n\"\n') 510 fd.write('\"-----------------------------------------\\n\"\n') 511 buildhost = platform.node() 512 if os.environ.get('SOURCE_DATE_EPOCH'): 513 buildhost = "reproducible" 514 buildtime = datetime.datetime.utcfromtimestamp(int(os.environ.get('SOURCE_DATE_EPOCH', time.time()))) 515 fd.write('\"Libraries compiled on %s on %s \\n\"\n' % (buildtime, buildhost)) 516 fd.write('\"Machine characteristics: %s\\n\"\n' % (platform.platform())) 517 fd.write('\"Using PETSc directory: %s\\n\"\n' % (escape(self.installdir.petscDir))) 518 fd.write('\"Using PETSc arch: %s\\n\"\n' % (escape(self.installdir.petscArch))) 519 fd.write('\"-----------------------------------------\\n\";\n') 520 fd.write('static const char *petsccompilerinfo = \"\\n\"\n') 521 self.setCompilers.pushLanguage(self.languages.clanguage) 522 fd.write('\"Using C compiler: %s %s \\n\"\n' % (escape(self.setCompilers.getCompiler()), escape(self.setCompilers.getCompilerFlags()))) 523 self.setCompilers.popLanguage() 524 if hasattr(self.compilers, 'FC'): 525 self.setCompilers.pushLanguage('FC') 526 fd.write('\"Using Fortran compiler: %s %s %s\\n\"\n' % (escape(self.setCompilers.getCompiler()), escape(self.setCompilers.getCompilerFlags()), escape(self.setCompilers.CPPFLAGS))) 527 self.setCompilers.popLanguage() 528 fd.write('\"-----------------------------------------\\n\";\n') 529 fd.write('static const char *petsccompilerflagsinfo = \"\\n\"\n') 530 fd.write('\"Using include paths: %s\\n\"\n' % (escape(self.PETSC_CC_INCLUDES_INSTALL.replace('${PETSC_DIR}', self.installdir.petscDir)))) 531 fd.write('\"-----------------------------------------\\n\";\n') 532 fd.write('static const char *petsclinkerinfo = \"\\n\"\n') 533 self.setCompilers.pushLanguage(self.languages.clanguage) 534 fd.write('\"Using C linker: %s\\n\"\n' % (escape(self.setCompilers.getLinker()))) 535 self.setCompilers.popLanguage() 536 if hasattr(self.compilers, 'FC'): 537 self.setCompilers.pushLanguage('FC') 538 fd.write('\"Using Fortran linker: %s\\n\"\n' % (escape(self.setCompilers.getLinker()))) 539 self.setCompilers.popLanguage() 540 fd.write('\"Using libraries: %s%s -L%s %s %s\\n\"\n' % (escape(self.setCompilers.CSharedLinkerFlag), escape(os.path.join(self.installdir.petscDir, self.installdir.petscArch, 'lib')), escape(os.path.join(self.installdir.petscDir, self.installdir.petscArch, 'lib')), escape(self.petsclib), escape(self.PETSC_EXTERNAL_LIB_BASIC))) 541 fd.write('\"-----------------------------------------\\n\";\n') 542 fd.close() 543 return 544 545 def configurePrefetch(self): 546 '''Sees if there are any prefetch functions supported''' 547 if config.setCompilers.Configure.isSolaris(self.log) or self.framework.argDB['with-ios'] or not self.framework.argDB['with-prefetch']: 548 self.addDefine('Prefetch(a,b,c)', ' ') 549 return 550 self.pushLanguage(self.languages.clanguage) 551 if self.checkLink('#include <xmmintrin.h>', 'void *v = 0;_mm_prefetch((const char*)v,_MM_HINT_NTA);\n'): 552 # The Intel Intrinsics manual [1] specifies the prototype 553 # 554 # void _mm_prefetch(char const *a, int sel); 555 # 556 # but other vendors seem to insist on using subtly different 557 # prototypes, including void* for the pointer, and an enum for 558 # sel. These are both reasonable changes, but negatively impact 559 # portability. 560 # 561 # [1] https://software.intel.com/file/6373 562 self.addDefine('HAVE_XMMINTRIN_H', 1) 563 self.addDefine('Prefetch(a,b,c)', '_mm_prefetch((const char*)(a),(c))') 564 self.addDefine('PREFETCH_HINT_NTA', '_MM_HINT_NTA') 565 self.addDefine('PREFETCH_HINT_T0', '_MM_HINT_T0') 566 self.addDefine('PREFETCH_HINT_T1', '_MM_HINT_T1') 567 self.addDefine('PREFETCH_HINT_T2', '_MM_HINT_T2') 568 elif self.checkLink('#include <xmmintrin.h>', 'void *v = 0;_mm_prefetch(v,_MM_HINT_NTA);\n'): 569 self.addDefine('HAVE_XMMINTRIN_H', 1) 570 self.addDefine('Prefetch(a,b,c)', '_mm_prefetch((const void*)(a),(c))') 571 self.addDefine('PREFETCH_HINT_NTA', '_MM_HINT_NTA') 572 self.addDefine('PREFETCH_HINT_T0', '_MM_HINT_T0') 573 self.addDefine('PREFETCH_HINT_T1', '_MM_HINT_T1') 574 self.addDefine('PREFETCH_HINT_T2', '_MM_HINT_T2') 575 elif self.checkLink('', 'void *v = 0;__builtin_prefetch(v,0,0);\n'): 576 # From GCC docs: void __builtin_prefetch(const void *addr,int rw,int locality) 577 # 578 # The value of rw is a compile-time constant one or zero; one 579 # means that the prefetch is preparing for a write to the memory 580 # address and zero, the default, means that the prefetch is 581 # preparing for a read. The value locality must be a compile-time 582 # constant integer between zero and three. A value of zero means 583 # that the data has no temporal locality, so it need not be left 584 # in the cache after the access. A value of three means that the 585 # data has a high degree of temporal locality and should be left 586 # in all levels of cache possible. Values of one and two mean, 587 # respectively, a low or moderate degree of temporal locality. 588 # 589 # Here we adopt Intel's x86/x86-64 naming scheme for the locality 590 # hints. Using macros for these values in necessary since some 591 # compilers require an enum. 592 self.addDefine('Prefetch(a,b,c)', '__builtin_prefetch((a),(b),(c))') 593 self.addDefine('PREFETCH_HINT_NTA', '0') 594 self.addDefine('PREFETCH_HINT_T0', '3') 595 self.addDefine('PREFETCH_HINT_T1', '2') 596 self.addDefine('PREFETCH_HINT_T2', '1') 597 else: 598 self.addDefine('Prefetch(a,b,c)', ' ') 599 self.popLanguage() 600 601 def delGenFiles(self): 602 '''Delete generated files''' 603 delfile = os.path.join(self.arch.arch,'lib','petsc','conf','files') 604 try: 605 os.unlink(delfile) 606 except: pass 607 608 def configureAtoll(self): 609 '''Checks if atoll exists''' 610 if self.checkLink('#define _POSIX_C_SOURCE 200112L\n#include <stdlib.h>','long v = atoll("25");\n(void)v') or self.checkLink ('#include <stdlib.h>','long v = atoll("25");\n(void)v'): 611 self.addDefine('HAVE_ATOLL', '1') 612 613 def configureUnused(self): 614 '''Sees if __attribute((unused)) is supported''' 615 if self.framework.argDB['with-ios']: 616 self.addDefine('UNUSED', ' ') 617 return 618 self.pushLanguage(self.languages.clanguage) 619 if self.checkLink('__attribute((unused)) static int myfunc(__attribute((unused)) void *name){ return 1;}', 'int i = 0;\nint j = myfunc(&i);\n(void)j;\ntypedef void* atype;\n__attribute((unused)) atype a'): 620 self.addDefine('UNUSED', '__attribute((unused))') 621 else: 622 self.addDefine('UNUSED', ' ') 623 self.popLanguage() 624 625 def configureIsatty(self): 626 '''Check if the Unix C function isatty() works correctly 627 Actually just assumes it does not work correctly on batch systems''' 628 if not self.framework.argDB['with-batch']: 629 self.addDefine('USE_ISATTY',1) 630 631 def configureDeprecated(self): 632 '''Check if __attribute((deprecated)) is supported''' 633 def checkDeprecated(macro_base, src, is_intel): 634 ''' 635 run through the various attribute deprecated combinations and define MACRO_BAS(why) to the result 636 it if it compiles. 637 638 If none of the combos work, defines MACRO_BASE(why) as empty 639 ''' 640 full_macro_name = macro_base + '(why)' 641 for prefix in ('__attribute__', '__attribute','__declspec'): 642 if prefix == '__declspec': 643 # declspec does not have an extra set of brackets around the arguments 644 attr_bodies = ('deprecated(why)', 'deprecated') 645 else: 646 attr_bodies = ('(deprecated(why))', '(deprecated)') 647 648 for attr_body in attr_bodies: 649 attr_def = '{}({})'.format(prefix, attr_body) 650 test_src = '\n'.join(( 651 '#define {} {}'.format(full_macro_name, attr_def), 652 src.format(macro_base + '("asdasdadsasd")') 653 )) 654 if self.checkCompile(test_src, ''): 655 self.logPrint('configureDeprecated: \'{}\' appears to work'.format(attr_def)) 656 if is_intel and '(why)' in attr_body: 657 self.logPrint('configureDeprecated: Intel has conspired to make a supremely environment-sensitive compiler. The Intel compiler looks at the gcc executable in the environment to determine the language compatibility that it should attempt to emulate. Some important Cray installations have built PETSc using the Intel compiler, but with a newer gcc module loaded (e.g. 4.7). Thus at PETSc configure time, the Intel compiler decides to support the string argument, but the gcc found in the default user environment is older and does not support the argument.\n'.format(attr_def)) 658 self.logPrint('*** WE WILL THEREFORE REJECT \'{}\' AND CONTINUE TESTING ***'.format(attr_def)) 659 continue 660 self.addDefine(full_macro_name, attr_def) 661 return 662 663 self.addDefine(full_macro_name, ' ') 664 return 665 666 lang = self.languages.clanguage 667 with self.Language(lang): 668 is_intel = self.setCompilers.isIntel(self.getCompiler(lang=lang), self.log) 669 checkDeprecated('DEPRECATED_FUNCTION', '{} int myfunc(void) {{ return 1; }}', is_intel) 670 checkDeprecated('DEPRECATED_TYPEDEF', 'typedef int my_int {};', is_intel) 671 checkDeprecated('DEPRECATED_ENUM', 'enum E {{ oldval {}, newval }};', is_intel) 672 # I was unable to make a CPP macro that takes the old and new values as separate 673 # arguments and builds the message needed by _Pragma hence the deprecation message is 674 # handled as it is 675 if self.checkCompile('#define TEST _Pragma("GCC warning \"Testing _Pragma\"") value'): 676 self.addDefine('DEPRECATED_MACRO(why)', '_Pragma(why)') 677 else: 678 self.addDefine('DEPRECATED_MACRO(why)', ' ') 679 680 def configureAlign(self): 681 '''Check if __attribute(aligned) is supported''' 682 code = '''\ 683struct mystruct {int myint;} __attribute((aligned(16))); 684char assert_aligned[(sizeof(struct mystruct)==16)*2-1]; 685''' 686 self.pushLanguage(self.languages.clanguage) 687 if self.checkCompile(code): 688 self.addDefine('ATTRIBUTEALIGNED(size)', '__attribute((aligned(size)))') 689 self.addDefine('HAVE_ATTRIBUTEALIGNED', 1) 690 else: 691 self.framework.logPrint('Incorrect attribute(aligned)') 692 self.addDefine('ATTRIBUTEALIGNED(size)', ' ') 693 self.popLanguage() 694 return 695 696 def configureExpect(self): 697 '''Sees if the __builtin_expect directive is supported''' 698 self.pushLanguage(self.languages.clanguage) 699 if self.checkLink('', 'if (__builtin_expect(0,1)) return 1;'): 700 self.addDefine('HAVE_BUILTIN_EXPECT', 1) 701 self.popLanguage() 702 703 def configureFunctionName(self): 704 '''Sees if the compiler supports __func__ or a variant.''' 705 def getFunctionName(lang): 706 name = '"unknown"' 707 self.pushLanguage(lang) 708 for fname in ['__func__','__FUNCTION__','__extension__ __func__']: 709 code = "if ("+fname+"[0] != 'm') return 1;" 710 if self.checkCompile('',code) and self.checkLink('',code): 711 name = fname 712 break 713 self.popLanguage() 714 return name 715 langs = [] 716 717 self.addDefine('FUNCTION_NAME_C', getFunctionName('C')) 718 if hasattr(self.compilers, 'CXX'): 719 self.addDefine('FUNCTION_NAME_CXX', getFunctionName('Cxx')) 720 721 def configureIntptrt(self): 722 '''Determine what to use for uintptr_t and intptr_t''' 723 def staticAssertSizeMatchesVoidStar(inc,typename): 724 # The declaration is an error if either array size is negative. 725 # It should be okay to use an int that is too large, but it would be very unlikely for this to be the case 726 return self.checkCompile(inc, ('#define STATIC_ASSERT(cond) char negative_length_if_false[2*(!!(cond))-1]\n' 727 + 'STATIC_ASSERT(sizeof(void*) == sizeof(%s));'%typename)) 728 729 def generate_uintptr_guesses(): 730 for suff in ('max', '64', '32', '16'): 731 yield '#include <stdint.h>', 'uint{}_t'.format(suff), 'PRIx{}'.format(suff.upper()) 732 yield '#include <stdlib.h>\n#include <string.h>', 'size_t', 'zx' 733 yield '', 'unsigned long long', 'llx' 734 yield '', 'unsigned long', 'lx' 735 yield '', 'unsigned', 'x' 736 737 def generate_intptr_guesses(): 738 for suff in ('max', '64', '32', '16'): 739 yield '#include <stdint.h>', 'int{}_t'.format(suff), 'PRIx{}'.format(suff.upper()) 740 yield '', 'long long', 'llx' 741 yield '', 'long', 'lx' 742 yield '', 'int', 'x' 743 744 def check(default_typename, generator): 745 macro_name = default_typename.upper() 746 with self.Language(self.languages.clanguage): 747 if self.checkCompile( 748 '#include <stdint.h>', 749 'int x; {type_name} i = ({type_name})&x; (void)i'.format(type_name=default_typename) 750 ): 751 typename = default_typename 752 print_format = 'PRIxPTR' 753 else: 754 for include, typename, print_format in generator(): 755 if staticAssertSizeMatchesVoidStar(include, typename): 756 break 757 else: 758 raise RuntimeError('Could not find any {} type matching void*'.format(macro_name)) 759 self.addDefine(macro_name , typename) 760 self.addDefine(macro_name + '_FMT', '\"#\" ' + print_format) 761 return 762 763 check('uintptr_t', generate_uintptr_guesses) 764 check('intptr_t', generate_intptr_guesses) 765 return 766 767 def configureRTLDDefault(self): 768 '''Check for dynamic library feature''' 769 if self.checkCompile('#include <dlfcn.h>\n void *ptr = RTLD_DEFAULT;'): 770 self.addDefine('HAVE_RTLD_DEFAULT','1') 771 return 772 773 def configureSolaris(self): 774 '''Solaris specific stuff''' 775 if os.path.isdir(os.path.join('/usr','ucblib')): 776 try: 777 flag = getattr(self.setCompilers, self.language[-1]+'SharedLinkerFlag') 778 except AttributeError: 779 flag = None 780 if flag is None: 781 self.compilers.LIBS += ' -L/usr/ucblib' 782 else: 783 self.compilers.LIBS += ' '+flag+'/usr/ucblib' 784 return 785 786 def configureDarwin(self): 787 '''Log brew configuration for Apple systems''' 788 try: 789 self.executeShellCommand(['brew', 'config'], log = self.log) 790 self.executeShellCommand(['brew', 'info', 'gcc'], log = self.log) 791 except: 792 pass 793 return 794 795 def configureLinux(self): 796 '''Linux specific stuff''' 797 # TODO: Test for this by mallocing an odd number of floats and checking the address 798 self.addDefine('HAVE_DOUBLE_ALIGN_MALLOC', 1) 799 return 800 801 def configureWin32(self): 802 '''Win32 non-cygwin specific stuff''' 803 kernel32=0 804 if self.libraries.add('Kernel32.lib','GetComputerName',prototype='#include <windows.h>', call='GetComputerName(NULL,NULL);'): 805 self.addDefine('HAVE_WINDOWS_H',1) 806 self.addDefine('HAVE_GETCOMPUTERNAME',1) 807 kernel32=1 808 elif self.libraries.add('kernel32','GetComputerName',prototype='#include <windows.h>', call='GetComputerName(NULL,NULL);'): 809 self.addDefine('HAVE_WINDOWS_H',1) 810 self.addDefine('HAVE_GETCOMPUTERNAME',1) 811 kernel32=1 812 if kernel32: 813 if self.framework.argDB['with-windows-graphics']: 814 self.addDefine('USE_WINDOWS_GRAPHICS',1) 815 if self.checkLink('#include <windows.h>','LoadLibrary(0)'): 816 self.addDefine('HAVE_LOADLIBRARY',1) 817 if self.checkLink('#include <windows.h>','GetProcAddress(0,0)'): 818 self.addDefine('HAVE_GETPROCADDRESS',1) 819 if self.checkLink('#include <windows.h>','FreeLibrary(0)'): 820 self.addDefine('HAVE_FREELIBRARY',1) 821 if self.checkLink('#include <windows.h>','GetLastError()'): 822 self.addDefine('HAVE_GETLASTERROR',1) 823 if self.checkLink('#include <windows.h>','SetLastError(0)'): 824 self.addDefine('HAVE_SETLASTERROR',1) 825 if self.checkLink('#include <windows.h>\n','QueryPerformanceCounter(0);\n'): 826 self.addDefine('USE_MICROSOFT_TIME',1) 827 if self.libraries.add('Advapi32.lib','GetUserName',prototype='#include <windows.h>', call='GetUserName(NULL,NULL);'): 828 self.addDefine('HAVE_GET_USER_NAME',1) 829 elif self.libraries.add('advapi32','GetUserName',prototype='#include <windows.h>', call='GetUserName(NULL,NULL);'): 830 self.addDefine('HAVE_GET_USER_NAME',1) 831 832 if not self.libraries.add('User32.lib','GetDC',prototype='#include <windows.h>',call='GetDC(0);'): 833 self.libraries.add('user32','GetDC',prototype='#include <windows.h>',call='GetDC(0);') 834 if not self.libraries.add('Gdi32.lib','CreateCompatibleDC',prototype='#include <windows.h>',call='CreateCompatibleDC(0);'): 835 self.libraries.add('gdi32','CreateCompatibleDC',prototype='#include <windows.h>',call='CreateCompatibleDC(0);') 836 837 self.types.check('int32_t', 'int') 838 if not self.checkCompile('#include <sys/types.h>\n','uid_t u;\n(void)u'): 839 self.addTypedef('int', 'uid_t') 840 self.addTypedef('int', 'gid_t') 841 if not self.checkLink('#if defined(PETSC_HAVE_UNISTD_H)\n#include <unistd.h>\n#endif\n','int a=R_OK;\n(void)a'): 842 self.framework.addDefine('R_OK', '04') 843 self.framework.addDefine('W_OK', '02') 844 self.framework.addDefine('X_OK', '01') 845 if not self.checkLink('#include <sys/stat.h>\n','int a=0;\nif (S_ISDIR(a)){}\n'): 846 self.framework.addDefine('S_ISREG(a)', '(((a)&_S_IFMT) == _S_IFREG)') 847 self.framework.addDefine('S_ISDIR(a)', '(((a)&_S_IFMT) == _S_IFDIR)') 848 if self.checkCompile('#include <windows.h>\n','LARGE_INTEGER a;\nDWORD b=a.u.HighPart;\n'): 849 self.addDefine('HAVE_LARGE_INTEGER_U',1) 850 851 # Windows requires a Binary file creation flag when creating/opening binary files. Is a better test in order? 852 if self.checkCompile('#include <windows.h>\n#include <fcntl.h>\n', 'int flags = O_BINARY;'): 853 self.addDefine('HAVE_O_BINARY',1) 854 855 if self.compilers.CC.find('win32fe') >= 0: 856 self.addDefine('HAVE_WINDOWS_COMPILERS',1) 857 self.addDefine('DIR_SEPARATOR','\'\\\\\'') 858 self.addDefine('REPLACE_DIR_SEPARATOR','\'/\'') 859 self.addDefine('CANNOT_START_DEBUGGER',1) 860 (petscdir,error,status) = self.executeShellCommand('cygpath -w '+self.installdir.petscDir, log = self.log) 861 self.addDefine('DIR','"'+petscdir.replace('\\','\\\\')+'"') 862 (petscdir,error,status) = self.executeShellCommand('cygpath -m '+self.installdir.petscDir, log = self.log) 863 self.addMakeMacro('wPETSC_DIR',petscdir) 864 if self.dataFilesPath.datafilespath: 865 (datafilespath,error,status) = self.executeShellCommand('cygpath -m '+self.dataFilesPath.datafilespath, log = self.log) 866 self.addMakeMacro('DATAFILESPATH',datafilespath) 867 868 else: 869 self.addDefine('REPLACE_DIR_SEPARATOR','\'\\\\\'') 870 self.addDefine('DIR_SEPARATOR','\'/\'') 871 self.addDefine('DIR','"'+self.installdir.petscDir+'"') 872 self.addMakeMacro('wPETSC_DIR',self.installdir.petscDir) 873 if self.dataFilesPath.datafilespath: 874 self.addMakeMacro('DATAFILESPATH',self.dataFilesPath.datafilespath) 875 self.addDefine('ARCH','"'+self.installdir.petscArch+'"') 876 return 877 878 def configureCoverageForLang(self, log_printer_cls, lang, extra_coverage_flags=None, extra_debug_flags=None): 879 """ 880 Check that a compiler accepts code-coverage flags. If the compiler does accept code-coverage flags 881 try to set debugging flags equivalent to -Og. 882 883 Arguments: 884 - lang: the language to check the coverage flag for 885 - extra_coverage_flags: a list of extra flags to use when checking the coverage flags 886 - extra_debug_flags: a list of extra flags to try when setting debug flags 887 888 On success: 889 - defines PETSC_USE_COVERAGE to 1 890 """ 891 log_print = log_printer_cls(self) 892 893 def quoted(string): 894 return string.join(("'", "'")) 895 896 def make_flag_list(default, extra): 897 ret = [default] 898 if extra is not None: 899 assert isinstance(extra, list) 900 ret.extend(extra) 901 return ret 902 903 log_print('Checking coverage flag for language {}'.format(lang)) 904 905 compiler = self.getCompiler(lang=lang) 906 if self.setCompilers.isGNU(compiler, self.log): 907 is_gnuish = True 908 elif self.setCompilers.isClang(compiler, self.log): 909 is_gnuish = True 910 else: 911 is_gnuish = False 912 913 # if not gnuish and we don't have a set of extra flags, bail 914 if not is_gnuish and extra_coverage_flags is None: 915 log_print('Don\'t know how to add coverage for compiler {}. Only know how to add coverage for gnu-like compilers (either gcc or clang). Skipping it!'.format(quoted(compiler))) 916 return 917 918 coverage_flags = make_flag_list('--coverage', extra_coverage_flags) 919 log_print('Checking set of coverage flags: {}'.format(coverage_flags)) 920 921 found = None 922 with self.Language(lang): 923 with self.setCompilers.Language(lang): 924 for flag in coverage_flags: 925 # the linker also needs to see the coverage flag 926 with self.setCompilers.extraCompilerFlags([flag], compilerOnly=False) as skip_flags: 927 if not skip_flags and self.checkRun(): 928 # flag was accepted 929 found = flag 930 break 931 932 log_print( 933 'Compiler {} did not accept coverage flag {}'.format(quoted(compiler), quoted(flag)) 934 ) 935 936 if found is None: 937 log_print( 938 'Compiler {} did not accept ANY coverage flags: {}, bailing!'.format( 939 quoted(compiler), coverage_flags 940 ) 941 ) 942 return 943 944 # must do this exactly here since: 945 # 946 # 1. setCompilers.extraCompilerFlags() will reset the compiler flags on __exit__() 947 # (so cannot do it in the loop) 948 # 2. we need to set the compiler flag while setCompilers.Language() is still in 949 # effect (so cannot do it outside the with statements) 950 self.setCompilers.insertCompilerFlag(flag, False) 951 952 if not self.functions.haveFunction('__gcov_dump'): 953 self.functions.checkClassify(['__gcov_dump']) 954 955 # now check if we can override the optimization level. It is only kosher to do so if 956 # the user did not explicitly set the optimization flags (via CFLAGS, CXXFLAGS, 957 # CXXOPTFLAGS, etc). If they have done so, we sternly warn them about their lapse in 958 # judgement 959 with self.Language(lang): 960 compiler_flags = self.getCompilerFlags() 961 962 user_set = 0 963 allowed_opt_flags = re.compile(r'|'.join((r'-O[01g]', r'-g[1-9]*'))) 964 for flagsname in [self.getCompilerFlagsName(lang), self.compilerFlags.getOptionalFlagsName(lang)]: 965 if flagsname in self.argDB: 966 opt_flags = [ 967 f for f in self.compilerFlags.findOptFlags(compiler_flags) if not allowed_opt_flags.match(f) 968 ] 969 if opt_flags: 970 self.logPrintWarning('Coverage requested, but optimization flag(s) {} found in {}. Coverage collection will work, but may be less accurate. Suggest removing the flag and/or using -Og (or equivalent) instead'.format(', '.join(map(quoted, opt_flags)), quoted(flagsname))) 971 user_set = 1 972 break 973 974 # disable this for now, the warning should be sufficient. If the user still chooses to 975 # ignore it, then that's on them 976 if 0 and not user_set: 977 debug_flags = make_flag_list('-Og', extra_debug_flags) 978 with self.setCompilers.Language(lang): 979 for flag in debug_flags: 980 try: 981 self.setCompilers.addCompilerFlag(flag) 982 except RuntimeError: 983 continue 984 break 985 986 self.addDefine('USE_COVERAGE', 1) 987 return 988 989 def configureCoverage(self): 990 """ 991 Configure coverage for all available languages. 992 993 If user did not request coverage, this function does nothing and returns immediatel. 994 Therefore the following only apply to the case where the user requested coverage. 995 996 On success: 997 - defines PETSC_USE_COVERAGE to 1 998 999 On failure: 1000 - If no compilers supported the coverage flag, throws RuntimeError 1001 - 1002 """ 1003 class LogPrinter: 1004 def __init__(self, cfg): 1005 self.cfg = cfg 1006 try: 1007 import inspect 1008 1009 calling_func_stack = inspect.stack()[1] 1010 if sys.version_info >= (3, 5): 1011 func_name = calling_func_stack.function 1012 else: 1013 func_name = calling_func_stack[3] 1014 except: 1015 func_name = 'Unknown' 1016 self.fmt_str = func_name + '(): {}' 1017 1018 def __call__(self, msg, *args, **kwargs): 1019 return self.cfg.logPrint(self.fmt_str.format(msg), *args, **kwargs) 1020 1021 argdb_flag = 'with-coverage' 1022 log_print = LogPrinter(self) 1023 if not self.argDB[argdb_flag]: 1024 log_print('coverage was disabled from command line or default') 1025 return 1026 1027 tested_langs = [] 1028 for LANG in ['C', 'Cxx', 'CUDA', 'HIP', 'SYCL', 'FC']: 1029 compilerName = LANG.upper() if LANG in {'Cxx', 'FC'} else LANG + 'C' 1030 if hasattr(self.setCompilers, compilerName): 1031 kwargs = {} 1032 if LANG in {'CUDA'}: 1033 # nvcc preprocesses the base file into a bunch of intermediate files, which are 1034 # then compiled by the host compiler. Why is this a problem? Because the 1035 # generated coverage data is based on these preprocessed source files! So gcov 1036 # tries to read it later, but since its in the tmp directory it cannot. Thus we 1037 # need to keep them around (in a place we know about). 1038 nvcc_tmp_dir = os.path.join(self.petscdir.dir, self.arch.arch, 'nvcc_tmp') 1039 try: 1040 os.mkdir(nvcc_tmp_dir) 1041 except FileExistsError: 1042 pass 1043 kwargs['extra_coverage_flags'] = [ 1044 '-Xcompiler --coverage -Xcompiler -fPIC --keep --keep-dir={}'.format(nvcc_tmp_dir) 1045 ] 1046 if self.kokkos.found: 1047 # yet again the kokkos nvcc_wrapper goes out of its way to be as useless as 1048 # possible. Its default arch (sm_35) is actually too low to compile kokkos, 1049 # for whatever reason this works if you dont use the --keep and --keep-dir 1050 # flags above. 1051 kwargs['extra_coverage_flags'].append('-arch=native') 1052 kwargs['extra_debug_flags'] = ['-Xcompiler -Og'] 1053 tested_langs.append(LANG) 1054 self.executeTest(self.configureCoverageForLang, args=[LogPrinter, LANG], kargs=kwargs) 1055 1056 if not self.defines.get('USE_COVERAGE'): 1057 # coverage was requested but no compilers accepted it, this is an error 1058 raise RuntimeError( 1059 'Coverage was requested (--{}={}) but none of the compilers supported it:\n{}\n'.format( 1060 argdb_flag, self.argDB[argdb_flag], 1061 '\n'.join([' - {} ({})'.format(self.getCompiler(lang=lang), lang) for lang in tested_langs]) 1062 ) 1063 ) 1064 1065 return 1066 # Disabled for now, since this does not really work. It solves the problem of 1067 # "undefined reference to __gcov_flush()" but if we add -lgcov we get: 1068 # 1069 # duplicate symbol '___gcov_reset' in: 1070 # /Library/.../libclang_rt.profile_osx.a(GCDAProfiling.c.o) 1071 # /opt/.../libgcov.a(_gcov_reset.o) 1072 # duplicate symbol '___gcov_dump' in: 1073 # /opt/.../libgcov.a(_gcov_dump.o) 1074 # /Library/.../libclang_rt.profile_osx.a(GCDAProfiling.c.o) 1075 # duplicate symbol '___gcov_fork' in: 1076 # /opt/.../libgcov.a(_gcov_fork.o) 1077 # /Library/.../libclang_rt.profile_osx.a(GCDAProfiling.c.o) 1078 # 1079 # I don't know how to solve this. 1080 1081 log_print('Checking if compilers can cross-link disparate coverage libraries') 1082 # At least one of the compilers has coverage enabled. Now need to make sure multiple 1083 # code coverage impls work together, specifically when using clang C/C++ compiler with 1084 # gfortran. 1085 if not hasattr(self.setCompilers, 'FC'): 1086 log_print('No fortran compiler detected. No need to check cross-linking!') 1087 return 1088 1089 c_lang = self.languages.clanguage 1090 if not self.setCompilers.isClang(self.getCompiler(lang=c_lang), self.log): 1091 # must be GCC 1092 log_print('C-language ({}) compiler is not clang, assuming it is GCC, so cross-linking with FC ({}) assumed to be OK'.format(c_lang, self.getCompiler(lang='FC'))) 1093 return 1094 1095 # If we are here we: 1096 # 1. Have both C/C++ compiler and fortran compiler 1097 # 2. The C/C++ compiler is *not* the same as the fortran compiler (unless we start 1098 # using flang) 1099 # 1100 # Now we check if we can cross-link 1101 def can_cross_link(**kwargs): 1102 f_body = " subroutine foo()\n print*,'testing'\n return\n end\n" 1103 c_body = "int main() { }" 1104 1105 return self.compilers.checkCrossLink( 1106 f_body, c_body, language1='FC', language2=c_lang, extralibs=self.compilers.flibs, **kwargs 1107 ) 1108 1109 log_print('Trying to cross-link WITHOUT extra libs') 1110 if can_cross_link(): 1111 log_print('Successfully cross-linked WITHOUT extra libs') 1112 # success, we already can cross-link 1113 return 1114 1115 extra_libs = ['-lgcov'] 1116 log_print('Trying to cross-link with extra libs: {}'.format(extra_libs)) 1117 if can_cross_link(extraObjs=extra_libs): 1118 log_print( 1119 'Successfully cross-linked using extra libs: {}, adding them to LIBS'.format(extra_libs) 1120 ) 1121 self.setCompilers.LIBS += ' ' + ' '.join(extra_libs) 1122 else: 1123 # maybe should be an error? 1124 self.logPrintWarning("Could not successfully cross-link covered code between {} and FC. Sometimes this is a false positive. Assuming this does eventually end up working when the full link-line is assembled when building PETSc. If you later encounter linker errors about missing __gcov_exit(), __gcov_init(), __llvm_cov_flush() etc. this is why!".format(c_lang)) 1125 return 1126 1127 def configureCoverageExecutable(self): 1128 """ 1129 Check that a code-coverage collecting tool exists and is on PATH. 1130 1131 On success: 1132 - Adds PETSC_COVERAGE_EXEC make macro containing the full path to the coverage tool executable. 1133 1134 Raises RuntimeError if: 1135 - User explicitly requests auto-detection of the coverage tool from command line, and this 1136 routine fails to guess the suitable tool name. 1137 - The routine fails to find the tool, and --with-coverage is true 1138 """ 1139 def log_print(msg, *args, **kwargs): 1140 self.logPrint('checkCoverage: '+str(msg), *args, **kwargs) 1141 return 1142 1143 def quoted(string): 1144 return string.join(("'", "'")) 1145 1146 required = bool(self.argDB['with-coverage']) 1147 arg_opt = self.argDB['with-coverage-exec'] 1148 use_default_path = True 1149 search_path = '' 1150 1151 log_print('{} to find an executable'.format('REQUIRED' if required else 'NOT required')) 1152 if arg_opt in {'auto', 'default-auto', '1'}: 1153 # detect it based on the C language compiler, hopefully this does not clash! 1154 lang = self.setCompilers.languages.clanguage 1155 compiler = self.getCompiler(lang=lang) 1156 log_print('User did not explicitly set coverage exec (got {}), trying to auto-detect based on compiler {}'.format(quoted(arg_opt), quoted(compiler))) 1157 if self.setCompilers.isGNU(compiler, self.log): 1158 compiler_version_re = re.compile(r'[gG][cC\+\-]+[0-9]* \(.+\) (\d+)\.(\d+)\.(\d+)') 1159 exec_names = ['gcov'] 1160 elif self.setCompilers.isClang(compiler, self.log): 1161 compiler_version_re = re.compile(r'clang version (\d+)\.(\d+)\.(\d+)') 1162 exec_names = ['llvm-cov'] 1163 if self.setCompilers.isDarwin(self.log): 1164 # macOS masquerades llvm-cov as just 'gcov', so we add this to the list in case 1165 # bare llvm-cov does not work 1166 exec_names.append('gcov') 1167 elif arg_opt == 'default-auto' and not required: 1168 # default-auto implies the user did not set it via command line! 1169 log_print('Could not auto-detect coverage tool for {}, not a gnuish compiler. Bailing since user did not explicitly set exec on the commandline'.format(quoted(compiler))) 1170 return 1171 else: 1172 # implies 'auto' explicitly set by user, or we were required to find 1173 # something. either way we should error 1174 raise RuntimeError('Could not auto-detect coverage tool for {}, please set coverage tool name explicitly'.format(quoted(compiler))) 1175 1176 try: 1177 compiler_version_str = self.compilerFlags.version[lang] 1178 except KeyError: 1179 compiler_version_str = 'Unknown' 1180 1181 log_print('Searching version string {} (for compiler {}) using pattern {}'.format(quoted(compiler_version_str), quoted(compiler), quoted(compiler_version_re.pattern))) 1182 compiler_version = compiler_version_re.search(compiler_version_str) 1183 if compiler_version is not None: 1184 log_print('Found major = {}, minor = {}, patch = {}'.format(compiler_version.group(1), compiler_version.group(2), compiler_version.group(3))) 1185 # form [llvm-cov-14, llvm-cov-14.0, llvm-cov, etc.] 1186 cov_exec_name = exec_names[0] 1187 exec_names = [ 1188 # llvm-cov-14 1189 '{}-{}'.format(cov_exec_name, compiler_version.group(1)), 1190 # llvm-cov-14.0 1191 '{}-{}.{}'.format(cov_exec_name, compiler_version.group(1), compiler_version.group(2)) 1192 ] + exec_names 1193 else: 1194 log_print('User explicitly set coverage exec as {}'.format(quoted(arg_opt))) 1195 par_dir = os.path.dirname(arg_opt) 1196 if os.path.exists(par_dir): 1197 # arg_opt is path-like, we should only search the provided directory when we go 1198 # looking for the tool 1199 use_default_path = False 1200 search_path = par_dir 1201 exec_names = [arg_opt] 1202 1203 make_macro_name = 'PETSC_COVERAGE_EXEC' 1204 log_print('Checking for coverage tool(s):\n{}'.format('\n'.join('- '+t for t in exec_names))) 1205 found_exec = self.getExecutables( 1206 exec_names, 1207 path=search_path, getFullPath=True, useDefaultPath=use_default_path, resultName=make_macro_name 1208 ) 1209 1210 if found_exec is None: 1211 # didn't find the coverage tool 1212 if required: 1213 raise RuntimeError('Coverage tool(s) {} could not be found. Please provide explicit path to coverage tool'.format(exec_names)) 1214 return 1215 1216 found_exec_name = os.path.basename(found_exec) 1217 if 'llvm-cov' in found_exec_name and 'gcov' not in found_exec_name: 1218 # llvm-cov needs to be called as 'llvm-cov gcov' to work 1219 self.addMakeMacro(make_macro_name, found_exec + ' gcov') 1220 return 1221 1222 def configureStrictPetscErrorCode(self): 1223 """ 1224 Enables or disables strict PetscErrorCode checking. 1225 1226 If --with-strict-petscerrorcode = 1: 1227 - defines PETSC_USE_STRICT_PETSCERRORCODE to 1 1228 1229 Else: 1230 - deletes any prior PETSC_USE_STRICT_PETSCERRORCODE definitions (if they exist) 1231 """ 1232 define_name = 'USE_STRICT_PETSCERRORCODE' 1233 if self.argDB['with-strict-petscerrorcode']: 1234 self.addDefine(define_name, 1) 1235 else: 1236 # in case it was somehow added previously 1237 self.delDefine(define_name) 1238 return 1239 1240#----------------------------------------------------------------------------------------------------- 1241 def configureCygwinBrokenPipe(self): 1242 '''Cygwin version <= 1.7.18 had issues with pipes and long commands invoked from gnu-make 1243 http://cygwin.com/ml/cygwin/2013-05/msg00340.html ''' 1244 if config.setCompilers.Configure.isCygwin(self.log): 1245 import platform 1246 import re 1247 r=re.compile("([0-9]+).([0-9]+).([0-9]+)") 1248 m=r.match(platform.release()) 1249 major=int(m.group(1)) 1250 minor=int(m.group(2)) 1251 subminor=int(m.group(3)) 1252 if ((major < 1) or (major == 1 and minor < 7) or (major == 1 and minor == 7 and subminor <= 18)): 1253 self.addMakeMacro('PETSC_CYGWIN_BROKEN_PIPE','1') 1254 return 1255 1256#----------------------------------------------------------------------------------------------------- 1257 def configureDefaultArch(self): 1258 conffile = os.path.join('lib','petsc','conf', 'petscvariables') 1259 if self.framework.argDB['with-default-arch']: 1260 fd = open(conffile, 'w') 1261 fd.write('PETSC_ARCH='+self.arch.arch+'\n') 1262 fd.write('PETSC_DIR='+self.petscdir.dir+'\n') 1263 fd.write('include '+os.path.join('$(PETSC_DIR)','$(PETSC_ARCH)','lib','petsc','conf','petscvariables')+'\n') 1264 fd.close() 1265 self.framework.actions.addArgument('PETSc', 'Build', 'Set default architecture to '+self.arch.arch+' in '+conffile) 1266 elif os.path.isfile(conffile): 1267 try: 1268 os.unlink(conffile) 1269 except: 1270 raise RuntimeError('Unable to remove file '+conffile+'. Did a different user create it?') 1271 return 1272 1273#----------------------------------------------------------------------------------------------------- 1274 def configureScript(self): 1275 '''Output a script in the conf directory which will reproduce the configuration''' 1276 import nargs 1277 import sys 1278 scriptName = os.path.join(self.arch.arch,'lib','petsc','conf', 'reconfigure-'+self.arch.arch+'.py') 1279 args = dict([(nargs.Arg.parseArgument(arg)[0], arg) for arg in self.framework.clArgs]) 1280 if 'with-clean' in args: 1281 del args['with-clean'] 1282 if 'force' in args: 1283 del args['force'] 1284 if 'configModules' in args: 1285 if nargs.Arg.parseArgument(args['configModules'])[1] == 'PETSc.Configure': 1286 del args['configModules'] 1287 if 'optionsModule' in args: 1288 if nargs.Arg.parseArgument(args['optionsModule'])[1] == 'config.compilerOptions': 1289 del args['optionsModule'] 1290 if not 'PETSC_ARCH' in args: 1291 args['PETSC_ARCH'] = 'PETSC_ARCH='+str(self.arch.arch) 1292 f = open(scriptName, 'w') 1293 f.write('#!'+sys.executable+'\n') 1294 f.write('if __name__ == \'__main__\':\n') 1295 f.write(' import sys\n') 1296 f.write(' import os\n') 1297 f.write(' sys.path.insert(0, os.path.abspath(\'config\'))\n') 1298 f.write(' import configure\n') 1299 # pretty print repr(args.values()) 1300 f.write(' configure_options = [\n') 1301 for itm in sorted(args.values()): 1302 f.write(' \''+str(itm)+'\',\n') 1303 f.write(' ]\n') 1304 f.write(' configure.petsc_configure(configure_options)\n') 1305 f.close() 1306 try: 1307 os.chmod(scriptName, 0o775) 1308 except OSError as e: 1309 self.framework.logPrint('Unable to make reconfigure script executable:\n'+str(e)) 1310 self.framework.actions.addArgument('PETSc', 'File creation', 'Created '+scriptName+' for automatic reconfiguration') 1311 return 1312 1313 def configureInstall(self): 1314 '''Setup the directories for installation''' 1315 if self.framework.argDB['prefix']: 1316 self.addMakeRule('print_mesg_after_build','', 1317 ['-@echo "========================================="', 1318 '-@echo "Now to install the libraries do:"', 1319 '-@echo "%s${MAKE_USER} PETSC_DIR=${PETSC_DIR} PETSC_ARCH=${PETSC_ARCH} install"' % self.installdir.installSudo, 1320 '-@echo "========================================="']) 1321 else: 1322 self.addMakeRule('print_mesg_after_build','', 1323 ['-@echo "========================================="', 1324 '-@echo "Now to check if the libraries are working do:"', 1325 '-@echo "${MAKE_USER} PETSC_DIR=${PETSC_DIR} PETSC_ARCH=${PETSC_ARCH} check"', 1326 '-@echo "========================================="']) 1327 return 1328 1329 def postProcessPackages(self): 1330 postPackages=[] 1331 for i in self.framework.packages: 1332 if hasattr(i,'postProcess'): postPackages.append(i) 1333 if postPackages: 1334 # ctetgen needs petsc conf files. so attempt to create them early 1335 self.framework.dumpConfFiles() 1336 # tacky fix for dependency of Aluimia on Pflotran; requested via petsc-dev Matt provide a correct fix 1337 for i in postPackages: 1338 if i.name.upper() in ['PFLOTRAN']: 1339 i.postProcess() 1340 postPackages.remove(i) 1341 for i in postPackages: i.postProcess() 1342 for i in postPackages: 1343 if i.installedpetsc: 1344 self.installed = 1 1345 break 1346 return 1347 1348 def configure(self): 1349 if 'package-prefix-hash' in self.argDB: 1350 # turn off prefix if it was only used to for installing external packages. 1351 self.framework.argDB['prefix'] = '' 1352 self.dir = os.path.abspath(os.path.join(self.petscdir.dir, self.arch.arch)) 1353 self.installdir.dir = self.dir 1354 self.installdir.petscDir = self.petscdir.dir 1355 self.petscDir = self.petscdir.dir 1356 self.petscArch = self.arch.arch 1357 self.addMakeMacro('PREFIXDIR',self.dir) 1358 self.confDir = os.path.abspath(os.path.join(self.petscdir.dir, self.arch.arch)) 1359 1360 if not os.path.samefile(self.petscdir.dir, os.getcwd()): 1361 raise RuntimeError('Wrong PETSC_DIR option specified: '+str(self.petscdir.dir) + '\n Configure invoked in: '+os.path.realpath(os.getcwd())) 1362 if self.framework.argDB['prefix'] and os.path.isdir(self.framework.argDB['prefix']) and os.path.samefile(self.framework.argDB['prefix'],self.petscdir.dir): 1363 raise RuntimeError('Incorrect option --prefix='+self.framework.argDB['prefix']+' specified. It cannot be same as PETSC_DIR!') 1364 if self.framework.argDB['prefix'] and self.framework.argDB['prefix'].find(' ') > -1: 1365 raise RuntimeError('Your --prefix '+self.framework.argDB['prefix']+' has spaces in it; this is not allowed.\n Use a --prefix that does not have spaces in it') 1366 if self.framework.argDB['prefix'] and os.path.isdir(self.framework.argDB['prefix']) and os.path.samefile(self.framework.argDB['prefix'],os.path.join(self.petscdir.dir,self.arch.arch)): 1367 raise RuntimeError('Incorrect option --prefix='+self.framework.argDB['prefix']+' specified. It cannot be same as PETSC_DIR/PETSC_ARCH!') 1368 self.framework.header = os.path.join(self.arch.arch,'include','petscconf.h') 1369 self.framework.cHeader = os.path.join(self.arch.arch,'include','petscfix.h') 1370 self.framework.poisonheader = os.path.join(self.arch.arch,'include','petscconf_poison.h') 1371 self.framework.pkgheader = os.path.join(self.arch.arch,'include','petscpkg_version.h') 1372 self.framework.makeMacroHeader = os.path.join(self.arch.arch,'lib','petsc','conf','petscvariables') 1373 self.framework.makeRuleHeader = os.path.join(self.arch.arch,'lib','petsc','conf','petscrules') 1374 if self.libraries.math is None: 1375 raise RuntimeError('PETSc requires a functional math library. Please send configure.log to petsc-maint@mcs.anl.gov.') 1376 if self.languages.clanguage == 'Cxx' and not hasattr(self.compilers, 'CXX'): 1377 raise RuntimeError('Cannot set C language to C++ without a functional C++ compiler.') 1378 self.executeTest(self.configureRTLDDefault) 1379 self.executeTest(self.configurePrefetch) 1380 self.executeTest(self.configureUnused) 1381 self.executeTest(self.configureDeprecated) 1382 self.executeTest(self.configureIsatty) 1383 self.executeTest(self.configureExpect) 1384 self.executeTest(self.configureAlign) 1385 self.executeTest(self.configureFunctionName) 1386 self.executeTest(self.configureIntptrt) 1387 self.executeTest(self.configureSolaris) 1388 self.executeTest(self.configureLinux) 1389 self.executeTest(self.configureDarwin) 1390 self.executeTest(self.configureWin32) 1391 self.executeTest(self.configureCygwinBrokenPipe) 1392 self.executeTest(self.configureDefaultArch) 1393 self.executeTest(self.configureScript) 1394 self.executeTest(self.configureInstall) 1395 self.executeTest(self.configureAtoll) 1396 self.executeTest(self.configureCoverage) 1397 self.executeTest(self.configureCoverageExecutable) 1398 self.executeTest(self.configureStrictPetscErrorCode) 1399 1400 self.Dump() 1401 self.dumpConfigInfo() 1402 self.dumpMachineInfo() 1403 self.delGenFiles() 1404 # need to save the current state of BuildSystem so that postProcess() packages can read it in and perhaps run make install 1405 self.framework.storeSubstitutions(self.framework.argDB) 1406 self.framework.argDB['configureCache'] = pickle.dumps(self.framework) 1407 self.framework.argDB.save(force = True) 1408 self.DumpPkgconfig('PETSc.pc') 1409 self.DumpPkgconfig('petsc.pc') 1410 self.DumpModule() 1411 self.postProcessPackages() 1412 self.framework.log.write('================================================================================\n') 1413 self.logClear() 1414 return 1415